Merge "Remove libdrm2. This code appears to be unused." into kraken
This commit is contained in:
committed by
Android (Google) Code Review
commit
ead68d5cd6
@@ -1,79 +0,0 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
# ---------------------------------------
|
||||
# First project
|
||||
#
|
||||
# Build DRM2 core library
|
||||
#
|
||||
# Output: libdrm2.so
|
||||
# ---------------------------------------
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
common_SRC_FILES := \
|
||||
src/util/ustl-1.0/bktrace.cpp \
|
||||
src/util/ustl-1.0/memblock.cpp \
|
||||
src/util/ustl-1.0/ofstream.cpp \
|
||||
src/util/ustl-1.0/ualgobase.cpp \
|
||||
src/util/ustl-1.0/unew.cpp \
|
||||
src/util/ustl-1.0/cmemlink.cpp \
|
||||
src/util/ustl-1.0/memlink.cpp \
|
||||
src/util/ustl-1.0/sistream.cpp \
|
||||
src/util/ustl-1.0/ubitset.cpp \
|
||||
src/util/ustl-1.0/ustdxept.cpp \
|
||||
src/util/ustl-1.0/fstream.cpp \
|
||||
src/util/ustl-1.0/mistream.cpp \
|
||||
src/util/ustl-1.0/sostream.cpp \
|
||||
src/util/ustl-1.0/uexception.cpp \
|
||||
src/util/ustl-1.0/ustring.cpp \
|
||||
src/util/xml/DomExpatAgent.cpp \
|
||||
src/util/xml/ExpatWrapper.cpp \
|
||||
src/util/xml/XMLDocumentImpl.cpp \
|
||||
src/util/xml/XMLElementImpl.cpp \
|
||||
src/util/domcore/CharacterDataImpl.cpp \
|
||||
src/util/domcore/ElementImpl.cpp \
|
||||
src/util/domcore/NodeListImpl.cpp \
|
||||
src/util/domcore/DocumentImpl.cpp \
|
||||
src/util/domcore/NodeImpl.cpp \
|
||||
src/util/domcore/TextImpl.cpp \
|
||||
src/util/domcore/DOMException.cpp \
|
||||
src/util/domcore/NodeIterator.cpp \
|
||||
src/util/crypto/DrmCrypto.cpp \
|
||||
src/rights/RoManager.cpp \
|
||||
src/rights/Asset.cpp \
|
||||
src/rights/Ro.cpp \
|
||||
src/rights/OperationPermission.cpp \
|
||||
src/rights/Right.cpp \
|
||||
src/rights/Constraint.cpp \
|
||||
src/drmmanager/DrmManager.cpp \
|
||||
src/dcf/DrmDcfCommon.cpp \
|
||||
src/dcf/DrmDcfContainer.cpp \
|
||||
src/dcf/DrmIStream.cpp \
|
||||
src/dcf/DrmRawContent.cpp \
|
||||
src/roap/RoapMessageHandler.cpp \
|
||||
src/roap/Registration.cpp
|
||||
|
||||
ifeq ($(TARGET_ARCH),arm)
|
||||
LOCAL_CFLAGS += -fstrict-aliasing -fomit-frame-pointer
|
||||
endif
|
||||
|
||||
common_CFLAGS := -W -g -DPLATFORM_ANDROID
|
||||
|
||||
common_C_INCLUDES +=\
|
||||
$(LOCAL_PATH)/include \
|
||||
$(LOCAL_PATH)/src/util/ustl-1.0 \
|
||||
external/expat/lib \
|
||||
external/openssl \
|
||||
external/openssl/include
|
||||
|
||||
LOCAL_SRC_FILES := $(common_SRC_FILES)
|
||||
LOCAL_CFLAGS += $(common_CFLAGS)
|
||||
LOCAL_C_INCLUDES += $(common_C_INCLUDES)
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := libexpat libcrypto
|
||||
LOCAL_MODULE := libdrm2
|
||||
|
||||
ifeq ($(TARGET_OS)-$(TARGET_ARCH),linux-x86)
|
||||
LOCAL_CFLAGS += -DUSTL_ANDROID_X86
|
||||
endif
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _DRM2COMMONTYPES_H_
|
||||
#define _DRM2COMMONTYPES_H_
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef DRM2_UT
|
||||
#define PROTECTED public
|
||||
#define PRIVATE public
|
||||
#else
|
||||
#define PROTECTED protected
|
||||
#define PRIVATE private
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __DCF_COMM_H__
|
||||
#define __DCF_COMM_H__
|
||||
|
||||
#include <Drm2CommonTypes.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <mistream.h>
|
||||
#include <ustring.h>
|
||||
|
||||
using namespace ustl;
|
||||
|
||||
////DCF box type list
|
||||
const uint32_t DCF_CONTAINER_BOX = uint32_t('m' << 24 | 'r' << 16 | 'd' << 8 | 'o');
|
||||
const uint32_t DCF_USER_TYPE = uint32_t('d' << 24 | 'i' << 16 | 'u' << 8 | 'u');
|
||||
const uint32_t DCF_FILE_TYPE = uint32_t('p' << 24 | 'y' << 16 | 't' << 8 | 'f');
|
||||
const uint32_t DCF_FILE_BRAND = uint32_t('f' << 24 | 'c' << 16 | 'd' << 8 | 'o');
|
||||
|
||||
|
||||
/**
|
||||
* The basic box class.
|
||||
*/
|
||||
class Box
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* constructor for Box, used to parse Box
|
||||
* \param box Box data
|
||||
*/
|
||||
Box(const uint8_t* box);
|
||||
|
||||
/**
|
||||
* copy constructor for Box
|
||||
* \param dcfBox Box object used to init a new Box object
|
||||
*/
|
||||
Box(const Box& dcfBox);
|
||||
|
||||
/**
|
||||
* assignment operator for Box
|
||||
* \param other Box object used to assign to a exist Box object
|
||||
*/
|
||||
Box& operator=(const Box& other);
|
||||
|
||||
/** Destructor for Box */
|
||||
virtual ~Box();
|
||||
|
||||
/**
|
||||
* get the size of Box
|
||||
* \param none
|
||||
* \return
|
||||
* the size
|
||||
*/
|
||||
uint64_t getSize(void) const;
|
||||
|
||||
/**
|
||||
* get the type of Box
|
||||
* \param none
|
||||
* \return
|
||||
* the type
|
||||
*/
|
||||
uint32_t getType(void) const;
|
||||
|
||||
/**
|
||||
* get the user type of Box
|
||||
* \param none
|
||||
* \return
|
||||
* the user type
|
||||
*/
|
||||
const uint8_t* getUsertype(void) const;
|
||||
|
||||
/**
|
||||
* get the length of Box
|
||||
* \param none
|
||||
* \return
|
||||
* the length
|
||||
*/
|
||||
virtual uint32_t getLen(void) const;
|
||||
PRIVATE:
|
||||
static const uint32_t USER_TYPE_LEN = 16;
|
||||
|
||||
uint32_t mSize;
|
||||
uint32_t mType;
|
||||
uint64_t mLargeSize;
|
||||
uint8_t* mUserType;
|
||||
uint32_t mBoxLength;
|
||||
};
|
||||
|
||||
/**
|
||||
* The fullBox class.
|
||||
*/
|
||||
class FullBox : public Box
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* constructor for FullBox, used to parse FullBox
|
||||
* \param fullBox FullBox data
|
||||
*/
|
||||
FullBox(const uint8_t* fullBox);
|
||||
|
||||
/** Destructor for FullBox */
|
||||
virtual ~FullBox(){}
|
||||
|
||||
/**
|
||||
* get the version of FullBox
|
||||
* \param none
|
||||
* \return
|
||||
* the version
|
||||
*/
|
||||
uint8_t getVersion(void) const;
|
||||
|
||||
/**
|
||||
* get the flag of FullBox
|
||||
* \param none
|
||||
* \return
|
||||
* the flag
|
||||
*/
|
||||
const uint8_t* getFlag(void) const;
|
||||
|
||||
/**
|
||||
* get the length of FullBox
|
||||
* \param none
|
||||
* \return
|
||||
* the length
|
||||
*/
|
||||
virtual uint32_t getLen(void) const;
|
||||
PRIVATE:
|
||||
static const uint32_t FLAG_LEN = 3;
|
||||
|
||||
uint8_t mVersion;
|
||||
uint8_t mFlag[FLAG_LEN];
|
||||
uint32_t mFullBoxLength;
|
||||
};
|
||||
|
||||
////// textal header class
|
||||
class TextualHeader
|
||||
{
|
||||
public:
|
||||
/** default constructor of DrmInStream */
|
||||
TextualHeader(){};
|
||||
|
||||
/**
|
||||
* constructor for TextualHeader, used to parse textal header
|
||||
* \param inData textal header data
|
||||
*/
|
||||
TextualHeader(const string& inData);
|
||||
|
||||
/**
|
||||
* get the name of textal header
|
||||
* \param none
|
||||
* \return
|
||||
* the name
|
||||
*/
|
||||
string getName() const;
|
||||
|
||||
/**
|
||||
* get the value of textal header
|
||||
* \param none
|
||||
* \return
|
||||
* the value
|
||||
*/
|
||||
string getValue() const;
|
||||
|
||||
/**
|
||||
* get the parameter of textal header
|
||||
* \param none
|
||||
* \return
|
||||
* the parameter
|
||||
*/
|
||||
string getParam() const;
|
||||
PRIVATE:
|
||||
string name;
|
||||
string value;
|
||||
string param;
|
||||
};
|
||||
|
||||
extern int64_t ntoh_int64(int64_t in);
|
||||
|
||||
#endif
|
||||
@@ -1,213 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __DCF_CONTAINER_H__
|
||||
#define __DCF_CONTAINER_H__
|
||||
|
||||
#include <Drm2CommonTypes.h>
|
||||
#include <uvector.h>
|
||||
#include <dcf/DrmIStream.h>
|
||||
#include <dcf/DrmDcfCommon.h>
|
||||
|
||||
class DrmInStream;
|
||||
|
||||
/////////dcf container
|
||||
class DcfContainer : public FullBox
|
||||
{
|
||||
public:
|
||||
friend class DrmInStream;
|
||||
|
||||
/** default constructor of DcfContainer */
|
||||
DcfContainer(istream& inRawData):FullBox(NULL),mConStream(inRawData){}
|
||||
|
||||
/**
|
||||
* constructor for DcfContainer, used to parse DCF container
|
||||
* \param data DCF container data
|
||||
* \param len DCF container data len
|
||||
* \param off the offset from the start of DCF container
|
||||
*/
|
||||
DcfContainer(const uint8_t* data,istream& inRawData,uint64_t conOff);
|
||||
|
||||
/** Destructor for DcfContainer */
|
||||
~DcfContainer();
|
||||
|
||||
/**
|
||||
* get the content type of one content
|
||||
* \param none
|
||||
* \return
|
||||
* the content type
|
||||
*/
|
||||
string getContentType(void) const;
|
||||
|
||||
/**
|
||||
* get the encryption method apply to content
|
||||
* \param none
|
||||
* \return
|
||||
* the encryption method
|
||||
*/
|
||||
uint8_t getEncryptionMethod(void) const;
|
||||
|
||||
/**
|
||||
* get the padding scheme apply to content
|
||||
* \param none
|
||||
* \return
|
||||
* the padding scheme
|
||||
*/
|
||||
uint8_t getPaddingScheme(void) const;
|
||||
|
||||
/**
|
||||
* get the length of plain content
|
||||
* \param none
|
||||
* \return
|
||||
* the length of plain content
|
||||
*/
|
||||
uint64_t getPlaintextLength(void) const;
|
||||
|
||||
/**
|
||||
* get the length of content ID
|
||||
* \param none
|
||||
* \return
|
||||
* the length of content ID
|
||||
*/
|
||||
uint16_t getContentIDLength(void) const;
|
||||
|
||||
/**
|
||||
* get the length of rights issuer URL
|
||||
* \param none
|
||||
* \return
|
||||
* the length of rights issuer URL
|
||||
*/
|
||||
uint16_t getRightsIssuerURLLength(void) const;
|
||||
|
||||
/**
|
||||
* get the length of textal header
|
||||
* \param none
|
||||
* \return
|
||||
* the length of textal header
|
||||
*/
|
||||
uint16_t getTextualHeadersLength(void) const;
|
||||
|
||||
/**
|
||||
* get the content ID of one content
|
||||
* \param none
|
||||
* \return
|
||||
* the content ID
|
||||
*/
|
||||
string getContentID(void) const;
|
||||
|
||||
/**
|
||||
* get the rights issuer URL
|
||||
* \param none
|
||||
* \return
|
||||
* the rights issuer URL
|
||||
*/
|
||||
string getRightsIssuerURL(void) const;
|
||||
|
||||
/**
|
||||
* get the preview method
|
||||
* \param none
|
||||
* \return
|
||||
* the preview method
|
||||
*/
|
||||
string getPreviewMethod(void) const;
|
||||
|
||||
/**
|
||||
* get the location of content
|
||||
* \param none
|
||||
* \return
|
||||
* the location of content
|
||||
*/
|
||||
string getContentLocation(void) const;
|
||||
|
||||
/**
|
||||
* get the URL of content
|
||||
* \param none
|
||||
* \return
|
||||
* the URL of content
|
||||
*/
|
||||
string getContentURL(void) const;
|
||||
|
||||
/**
|
||||
* get the customer head
|
||||
* \param none
|
||||
* \return
|
||||
* the customer head
|
||||
*/
|
||||
vector<string> getCustomerHead(void) const;
|
||||
|
||||
/**
|
||||
* get the preview element data
|
||||
* \param none
|
||||
* \return
|
||||
* the DRM Instream of preview element data
|
||||
*/
|
||||
DrmInStream getPreviewElementData(void) const;
|
||||
|
||||
/**
|
||||
* get the plain content
|
||||
* \param none
|
||||
* \return
|
||||
* the DRM Instream of plain content
|
||||
*/
|
||||
DrmInStream getDecryptContent(uint8_t* decryptKey) const;
|
||||
|
||||
/**
|
||||
* get the istream of DCF
|
||||
* \param none
|
||||
* \return
|
||||
* the istream of DCF
|
||||
*/
|
||||
istream& getStream(void) const;
|
||||
|
||||
PRIVATE:
|
||||
static const uint32_t USER_DATA_FLAG = 0x01;
|
||||
|
||||
uint8_t mContentTypeLen;
|
||||
string mContentType;
|
||||
uint8_t mEncryptionMethod;
|
||||
uint8_t mPaddingScheme;
|
||||
uint64_t mPlaintextLength;
|
||||
uint16_t mContentIDLength;
|
||||
uint16_t mRightsIssuerURLLength;
|
||||
uint16_t mTextualHeadersLength;
|
||||
string mContentID;
|
||||
string mRightsIssuerURL;
|
||||
vector<TextualHeader*> mTextualHeaders;
|
||||
bool mSilentFirst;
|
||||
string mSlientMethod;
|
||||
string mSilentRightsURL;
|
||||
string mPreviewMethod;
|
||||
string mPreviewElementURI;
|
||||
string mPreviewRightsURL;
|
||||
string mContentURL;
|
||||
string mContentVersion;
|
||||
string mContentLocation;
|
||||
vector<string> mCustomHeader;
|
||||
bool mHasUserData;
|
||||
uint64_t mDataLen;
|
||||
istream& mConStream;
|
||||
uint64_t mDecOffset;
|
||||
|
||||
PRIVATE:
|
||||
// parse text header
|
||||
bool parseTextualHeaders(const uint8_t* data, uint32_t len);
|
||||
void copy(const DcfContainer& container);
|
||||
DcfContainer(const DcfContainer& container):FullBox(NULL),mConStream(container.mConStream){}
|
||||
DcfContainer& operator=(const DcfContainer& other){return *this;}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __DRM_ISTREAM_H__
|
||||
#define __DRM_ISTREAM_H__
|
||||
|
||||
#include <Drm2CommonTypes.h>
|
||||
#include <util/crypto/DrmCrypto.h>
|
||||
#include <dcf/DrmDcfContainer.h>
|
||||
#include <ustring.h>
|
||||
|
||||
using namespace ustl;
|
||||
|
||||
class DcfContainer;
|
||||
|
||||
class DrmInStream
|
||||
{
|
||||
public:
|
||||
/** default constructor of DrmInStream */
|
||||
DrmInStream():mDecryptPos(0){}
|
||||
|
||||
/**
|
||||
* constructor for DrmInStream, used to read DCF content
|
||||
* \param encFile DCF container data
|
||||
* \param len DCF container data len
|
||||
* \param off the offset from the start of DCF container
|
||||
*/
|
||||
DrmInStream(const DcfContainer* container,uint8_t* Key);
|
||||
|
||||
/**
|
||||
* get the size of DRM Instream
|
||||
* \param none
|
||||
* \return
|
||||
* the size of DRM Instream
|
||||
*/
|
||||
uint64_t size() const;
|
||||
|
||||
/**
|
||||
* read data from DRM Instream
|
||||
* \param data the buffer to store read data
|
||||
* \param len how much data need to read
|
||||
* \return
|
||||
* the actual len of read data
|
||||
*/
|
||||
uint64_t read(uint8_t* data,uint64_t len);
|
||||
|
||||
PRIVATE:
|
||||
static const uint32_t AES_IV_LEN = 16;
|
||||
static const uint32_t AES_KEY_LEN = 16;
|
||||
static const uint32_t AES_BLOCK_LEN = 16;
|
||||
|
||||
const DcfContainer* mDcfCon;
|
||||
uint64_t mDecryptPos;
|
||||
uint8_t mAesKey[AES_KEY_LEN];
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __DRM_CONTENT_H__
|
||||
#define __DRM_CONTENT_H__
|
||||
|
||||
#include <Drm2CommonTypes.h>
|
||||
#include <dcf/DrmDcfContainer.h>
|
||||
|
||||
/////////////raw content
|
||||
class DrmRawContent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* constructor for DrmRawContent, used to parse DCF
|
||||
* \param inRawData input stream of raw data.
|
||||
*/
|
||||
DrmRawContent(istream& inRawData);
|
||||
|
||||
/** Destructor for DrmRawContent */
|
||||
~DrmRawContent();
|
||||
|
||||
/**
|
||||
* get DCF container
|
||||
* \param none
|
||||
* \return
|
||||
* the DCF container
|
||||
*/
|
||||
vector<DcfContainer*> getContents(void) const;
|
||||
|
||||
/**
|
||||
* get the length of DCF hash
|
||||
* \param none
|
||||
* \return
|
||||
* the length of DCF hash
|
||||
*/
|
||||
uint32_t getDcfHashLen() const;
|
||||
|
||||
/**
|
||||
* get DCF hash
|
||||
* \param outDcfHash the buffer to store DCF hash
|
||||
* \return
|
||||
* none
|
||||
*/
|
||||
void getDcfHash(uint8_t* outDcfHash) const;
|
||||
|
||||
PRIVATE:
|
||||
static const uint32_t DCF_HASH_LEN = 20;
|
||||
static const uint32_t FIX_HEADER_LEN = 20;
|
||||
static const uint32_t MAX_PIECE_LEN = (100 * 1024);
|
||||
|
||||
uint8_t mDcfHash[DCF_HASH_LEN];
|
||||
vector<DcfContainer*> mContainer;
|
||||
|
||||
PRIVATE:
|
||||
bool parseDcfHeader(const uint8_t* dcfHead);
|
||||
DrmRawContent(const DrmRawContent& rawContent){}
|
||||
DrmRawContent& operator=(const DrmRawContent& other){return *this;}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _DRMMANAGER_
|
||||
#define _DRMMANAGER_
|
||||
|
||||
#include <Drm2CommonTypes.h>
|
||||
#include <ofstream.h>
|
||||
#include <sostream.h>
|
||||
#include <ustring.h>
|
||||
#include <sistream.h>
|
||||
#include <uvector.h>
|
||||
|
||||
using namespace ustl;
|
||||
|
||||
/** It should be removed after real DcfContainer is ready */
|
||||
#define DcfContainer string
|
||||
static const int16_t DRM_OK = 1;
|
||||
|
||||
class DrmManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Error definition
|
||||
*/
|
||||
static const int16_t DRM_MANAGER_BASE = 100;
|
||||
static const int16_t ERR_DCFSTREAM_NOT_INITIALIZED = DRM_MANAGER_BASE+1;
|
||||
static const int16_t ERR_WRONG_DCFDATA = DRM_MANAGER_BASE+2;
|
||||
static const int16_t ERR_WRONG_RIGHTS = DRM_MANAGER_BASE+3;
|
||||
|
||||
/**
|
||||
* Constructor for DrmManager,used to open local dcf file.
|
||||
* @param inRawData input stream of raw data.
|
||||
*/
|
||||
DrmManager(istream *inRawData);
|
||||
|
||||
/**
|
||||
* Constructor for DrmManager,used to separate dcf file and trig message when upper
|
||||
* application downloading one multipart message from CI.
|
||||
* @param inRawData input stream of raw data.
|
||||
*/
|
||||
DrmManager(istream * inRawData, string mimeType);
|
||||
|
||||
/** Destructor for DomExpatAgent. */
|
||||
~DrmManager();
|
||||
/**
|
||||
* Config DRM engine
|
||||
* Fix me later
|
||||
*/
|
||||
bool config();
|
||||
|
||||
/**
|
||||
* Consume rights according to specified operation, DrmManager will check.
|
||||
* @param operationType the type of operation.
|
||||
* @return the operation result.
|
||||
*/
|
||||
int16_t consumeRights(int16_t operationType);
|
||||
|
||||
/**
|
||||
* Get the list of all dcf containers object reference in the dcf file.
|
||||
* @param the vector of the dcf objects list returned.
|
||||
* @return the operation result.
|
||||
*/
|
||||
int16_t getListOfDcfObjects(vector<DcfContainer*> **outDcfList);
|
||||
|
||||
/**
|
||||
* Open one Dcf container to read the decrypted data according to specified
|
||||
* operation.
|
||||
* @param oneDcfObject the reference of the DcfContainer.
|
||||
* @param operationType the type of operation.
|
||||
* @param decrypted data returned.
|
||||
* @return the operation result.
|
||||
*/
|
||||
int16_t openDecryptedContent(DcfContainer *oneDcfObject,
|
||||
int16_t operationType,
|
||||
istream *outDecryptedData);
|
||||
|
||||
/**
|
||||
* Get the separated Dcf raw data from multipart message.
|
||||
* @return the ifstream of the dcf raw data which should be stored by upper
|
||||
* application.
|
||||
*/
|
||||
ifstream* getOriginalMediaData(void);
|
||||
|
||||
/**
|
||||
* Handle DRM2.0 push message
|
||||
*/
|
||||
bool handlePushMsg(uint8_t* data, string mimeType);
|
||||
|
||||
PRIVATE:
|
||||
istream *mDcfStream; /**< the handler of dcf stream. */
|
||||
vector<DcfContainer*> mDcfs; /**< all the dcf containers included in one dcf file. */
|
||||
};
|
||||
|
||||
#endif //_DRMMANAGER_
|
||||
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _ASSET_H
|
||||
#define _ASSET_H
|
||||
|
||||
#include <ustring.h>
|
||||
#include <uvector.h>
|
||||
#include <Drm2CommonTypes.h>
|
||||
#include <rights/Right.h>
|
||||
using namespace ustl;
|
||||
|
||||
class Asset {
|
||||
public:
|
||||
/**
|
||||
* Constructor for asset.
|
||||
*/
|
||||
Asset();
|
||||
|
||||
/**
|
||||
* Destructor for asset.
|
||||
*/
|
||||
~Asset();
|
||||
|
||||
/**
|
||||
* Test whether asset has parent or not.
|
||||
* @return true/false to indicate the result.
|
||||
*/
|
||||
bool hasParent();
|
||||
|
||||
/**
|
||||
* Set id of asset.
|
||||
* @param id the id of asset.
|
||||
*/
|
||||
void setID(const string &id);
|
||||
|
||||
/**
|
||||
* Get the id of content.
|
||||
* @return asset id.
|
||||
*/
|
||||
const string& getID() const;
|
||||
|
||||
/**
|
||||
* Set contend id related to asset.
|
||||
* @param id the id of content.
|
||||
*/
|
||||
void setContentID(const string &id);
|
||||
|
||||
/**
|
||||
* Get content id.
|
||||
* @return content id.
|
||||
*/
|
||||
const string& getContentID() const;
|
||||
|
||||
/**
|
||||
* Set digest value of DCF.
|
||||
* @param value the DCF digest value.
|
||||
*/
|
||||
void setDCFDigest(const string &value);
|
||||
|
||||
/**
|
||||
* Get the DCF digest value.
|
||||
* @return the digest value of DCF.
|
||||
*/
|
||||
const string& getDCFDigest() const;
|
||||
|
||||
/**
|
||||
* Set encrypted key in asset.
|
||||
* @param the encrypted key.
|
||||
*/
|
||||
void setEncryptedKey(const string &key);
|
||||
|
||||
/**
|
||||
* Get encrypted key.
|
||||
* @return encypted key.
|
||||
*/
|
||||
const string& getEncrytedKey() const;
|
||||
|
||||
/**
|
||||
* Get cek.
|
||||
* @return cek.
|
||||
*/
|
||||
const char* getCek() const;
|
||||
|
||||
/**
|
||||
* Set the retrieval method of key.
|
||||
* @param rm the retrieval method of the key.
|
||||
*/
|
||||
void setKeyRetrievalMethod(const string &rm);
|
||||
|
||||
/**
|
||||
* Set parent content id for asset.
|
||||
* @param id the parent content id.
|
||||
*/
|
||||
void setParentContentID(const string &id);
|
||||
|
||||
/**
|
||||
* Get the parent content id of the asset.
|
||||
* @return the parent content id.
|
||||
*/
|
||||
const string& getParentContentID() const;
|
||||
|
||||
/**
|
||||
* Recover the CEK using private key.
|
||||
*/
|
||||
void recoverCek();
|
||||
|
||||
PRIVATE:
|
||||
string mAssetID;
|
||||
string mContentID;
|
||||
string mDigestMethod;
|
||||
string mDigestValue;
|
||||
string mEncryptedMethod;
|
||||
string mEncryptedKey;
|
||||
string mRetrievalMethod;
|
||||
string mParentContentID;
|
||||
string mCek;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,190 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _CONSTRAINT_H
|
||||
#define _CONSTRAINT_H
|
||||
|
||||
#include <Drm2CommonTypes.h>
|
||||
#include <ustring.h>
|
||||
#include <uvector.h>
|
||||
using namespace ustl;
|
||||
|
||||
struct Context {
|
||||
string id;
|
||||
string version;
|
||||
};
|
||||
|
||||
const int INIT_VALUE = -1;
|
||||
|
||||
class Constraint {
|
||||
public:
|
||||
enum MODE {NONE, MOVE, COPY}; /**< export mode type. */
|
||||
|
||||
/**
|
||||
* Construtor for constraint.
|
||||
*/
|
||||
Constraint();
|
||||
|
||||
/**
|
||||
* Destructor for constraint.
|
||||
*/
|
||||
~Constraint();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Test whether constraint is valid or not
|
||||
* @param time the specitic time to test.
|
||||
* @return true/false to indicate the result.
|
||||
*/
|
||||
bool isValid(long time) const;
|
||||
|
||||
/**
|
||||
* Test whether constraint is unconstraint or not
|
||||
* @return true/false to indicate the result.
|
||||
*/
|
||||
bool isUnConstraint() const;
|
||||
|
||||
/**
|
||||
* Test whether constraint is datetime related or not.
|
||||
* @return true/false to indicate the result.
|
||||
*/
|
||||
bool isDateTimeConstraint() const;
|
||||
|
||||
/**
|
||||
* Test whether constraint contain interval or not
|
||||
* @return true/false to indicate the result.
|
||||
*/
|
||||
bool isIntervalConstraint() const;
|
||||
|
||||
/**
|
||||
* Test whether constraint is timed count or not
|
||||
* @return true/false to indicate the result.
|
||||
*/
|
||||
bool isTimedCountConstraint() const;
|
||||
|
||||
/**
|
||||
* Set the start time value of constraint.
|
||||
* @param time the specific time value.
|
||||
*/
|
||||
void setStartTime(long time);
|
||||
|
||||
/**
|
||||
* Get the start time.
|
||||
* @return value of start time.
|
||||
*/
|
||||
long getStartTime() const;
|
||||
|
||||
/**
|
||||
* Set the end time.
|
||||
* @param time the value of end time.
|
||||
*/
|
||||
void setEndTime(long time);
|
||||
|
||||
/**
|
||||
* Get the end time.
|
||||
* @param return the value of end time.
|
||||
*/
|
||||
long getEndTime() const;
|
||||
|
||||
/**
|
||||
* Set the accumulated .
|
||||
* @param time the specific time.
|
||||
*/
|
||||
void setAccumulated(long time);
|
||||
|
||||
/**
|
||||
* Get the accumulated.
|
||||
* @return the value of accumulated
|
||||
*/
|
||||
long getAccumulated() const;
|
||||
|
||||
/**
|
||||
* Set the count.
|
||||
* @param count the value of count.
|
||||
*/
|
||||
void setCount(int count);
|
||||
|
||||
/**
|
||||
* Get the count.
|
||||
* @return value of count.
|
||||
*/
|
||||
int getCount() const;
|
||||
|
||||
/**
|
||||
* Set the value of timer.
|
||||
* @param timer the value of the timer.
|
||||
*/
|
||||
void setTimer(int timer);
|
||||
|
||||
/**
|
||||
* Get the timer.
|
||||
* @return value of time.
|
||||
*/
|
||||
int getTimer() const;
|
||||
|
||||
/**
|
||||
* Set the timedCount.
|
||||
* @param timedCount the value of timedCount.
|
||||
*/
|
||||
void setTimedCount(int timedCount);
|
||||
|
||||
/**
|
||||
* Get the timedCount.
|
||||
* @return the value of timedCount.
|
||||
*/
|
||||
int getTimedCount() const;
|
||||
|
||||
/**
|
||||
* Set the interval.
|
||||
* @param interval the value of interval.
|
||||
*/
|
||||
void setInterval(int interval);
|
||||
|
||||
/**
|
||||
* Get the interval.
|
||||
* @return the value of interval.
|
||||
*/
|
||||
int getInterval() const;
|
||||
|
||||
/**
|
||||
* set export mode.
|
||||
* @param mode the mode type of export.
|
||||
*/
|
||||
void setExportMode(MODE mode);
|
||||
|
||||
/**
|
||||
* Get the export mode.
|
||||
* @return the export mode.
|
||||
*/
|
||||
MODE getExportMode() const;
|
||||
|
||||
/**
|
||||
* Consume the constraint.
|
||||
* @return true/false to indicate whether consume succesfully or not.
|
||||
*/
|
||||
bool consume();
|
||||
|
||||
PRIVATE:
|
||||
int mCount; /**< the count. */
|
||||
int mTimedCount; /**< timed count. */
|
||||
int mTimer; /**< timer for timed count. */
|
||||
long mStart; /**< start time. */
|
||||
long mEnd; /**< end time. */
|
||||
int mInterval; /**< interval. */
|
||||
long mAccumulated; /**< accumlated. */
|
||||
vector<Context> mSystemList; /**< system list. */
|
||||
MODE mExport; /**< export mode. */
|
||||
};
|
||||
#endif
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _OPERATIONPERMISSION_H
|
||||
#define _OPERATIONPERMISSION_H
|
||||
|
||||
#include <Drm2CommonTypes.h>
|
||||
#include <rights/Constraint.h>
|
||||
|
||||
class OperationPermission {
|
||||
public:
|
||||
enum OPERATION {NONE, PLAY, DISPLAY, EXECUTE, PRINT, EXPORT, COMMON};
|
||||
|
||||
/**
|
||||
* Construtor of OperationPermission.
|
||||
*/
|
||||
OperationPermission();
|
||||
|
||||
/**
|
||||
* Construtor of OperationPermission.
|
||||
* @param type the specific operation type.
|
||||
* @param cst the constraint related with operation permission.
|
||||
*/
|
||||
OperationPermission(OPERATION type, Constraint* cst=NULL);
|
||||
|
||||
/**
|
||||
* Destrutor of OperationPermission.
|
||||
*/
|
||||
~OperationPermission();
|
||||
|
||||
/**
|
||||
* Set the type for operation permission.
|
||||
* @param type the specific type.
|
||||
*/
|
||||
void setType(OPERATION type);
|
||||
|
||||
/**
|
||||
* Get the type of operation permission.
|
||||
* @return operation type.
|
||||
*/
|
||||
OPERATION getType() const;
|
||||
|
||||
/**
|
||||
* Add constraint for operation permission.
|
||||
* @param constraint the constraint related with operation permission.
|
||||
*/
|
||||
void addConstraint(Constraint* constraint);
|
||||
|
||||
/**
|
||||
* Add constraint for operation permission.
|
||||
* @return constraint related with operation permission.
|
||||
*/
|
||||
Constraint* getConstraint() const;
|
||||
|
||||
PRIVATE:
|
||||
OPERATION mType;
|
||||
Constraint* mConstraint;
|
||||
|
||||
PRIVATE:
|
||||
/**
|
||||
* Disable the assignment between OperationPermissions.
|
||||
*/
|
||||
OperationPermission& operator=(const OperationPermission &op);
|
||||
|
||||
/**
|
||||
* Disable copy construtor.
|
||||
*/
|
||||
OperationPermission(const OperationPermission &op);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _RIGHT_H
|
||||
#define _RIGHT_H
|
||||
|
||||
#include <Drm2CommonTypes.h>
|
||||
#include <uvector.h>
|
||||
#include <ustring.h>
|
||||
#include <rights/Constraint.h>
|
||||
#include <rights/OperationPermission.h>
|
||||
using namespace ustl;
|
||||
|
||||
class Right {
|
||||
public:
|
||||
/**
|
||||
* Constructor for Right.
|
||||
*/
|
||||
Right();
|
||||
|
||||
/**
|
||||
* Destructor for Right.
|
||||
*/
|
||||
~Right();
|
||||
|
||||
/**
|
||||
* Add the asset id related with right into asset name list.
|
||||
* @param id the id of the asset.
|
||||
*/
|
||||
void addAssetID(const string& id);
|
||||
|
||||
/**
|
||||
* Add a operation permission into right's operation permission list.
|
||||
* @param op a pointer of operation permission.
|
||||
*/
|
||||
void addOperationPermission(OperationPermission* op);
|
||||
|
||||
/**
|
||||
* Get the constraint related with operation type.
|
||||
* @param type the specific operation type.
|
||||
* @return NULL if not found otherwise the constraint pointer.
|
||||
*/
|
||||
Constraint* getConstraint(OperationPermission::OPERATION type);
|
||||
|
||||
/**
|
||||
* Test whether the right has specific operation type or not.
|
||||
* @param type the specific type.
|
||||
* @return true/false to indicate the result.
|
||||
*/
|
||||
bool checkPermission(OperationPermission::OPERATION type);
|
||||
|
||||
public:
|
||||
vector<string> mAssetNameList;
|
||||
|
||||
PRIVATE:
|
||||
vector<OperationPermission*> mOpList;
|
||||
|
||||
PRIVATE:
|
||||
|
||||
/**
|
||||
* Disable the assignment between rights.
|
||||
*/
|
||||
Right& operator=(const Right& right);
|
||||
|
||||
/**
|
||||
* Disable copy constructor.
|
||||
*/
|
||||
Right(const Right& right);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,214 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _RO_H_
|
||||
#define _RO_H_
|
||||
|
||||
#include <rights/Asset.h>
|
||||
#include <rights/Right.h>
|
||||
#include <uvector.h>
|
||||
#include <ustring.h>
|
||||
#include <sistream.h>
|
||||
using namespace ustl;
|
||||
|
||||
class Asset;
|
||||
class XMLDocumentImpl;
|
||||
class XMLElementImpl;
|
||||
class NodeImpl;
|
||||
|
||||
class Ro {
|
||||
public:
|
||||
enum ERRCODE { RO_NULL_STREAM, RO_ERR_BAD_XML, RO_OK, RO_BAD };
|
||||
|
||||
/**
|
||||
* Constructor for Ro.
|
||||
*/
|
||||
Ro();
|
||||
|
||||
/**
|
||||
* Destructor for Ro.
|
||||
*/
|
||||
~Ro();
|
||||
|
||||
/**
|
||||
* Set id for Ro.
|
||||
* @param id the id of Ro.
|
||||
*/
|
||||
void setRoID(string &id);
|
||||
|
||||
/**
|
||||
* Get the id of Ro.
|
||||
* @return the id of Ro.
|
||||
*/
|
||||
const string& getRoID() const;
|
||||
|
||||
/**
|
||||
* Set version for Ro.
|
||||
*/
|
||||
void setRoVersion(string &version);
|
||||
|
||||
/**
|
||||
* Add a asset into ro's asset list.
|
||||
* @param asset the pointer of asset.
|
||||
*/
|
||||
void addAsset(Asset* asset);
|
||||
|
||||
/**
|
||||
* Add a right into ro's right list.
|
||||
* @param right the pointer of right.
|
||||
*/
|
||||
void addRight(Right* right);
|
||||
|
||||
/**
|
||||
* Save the Ro.
|
||||
*/
|
||||
bool save();
|
||||
|
||||
/**
|
||||
* Verify the Ro.
|
||||
*/
|
||||
bool verify();
|
||||
|
||||
/**
|
||||
* Parse the ro from stream.
|
||||
* @param roStream the input ro stream.
|
||||
* @return RO_OK if parse successfully otherwise return error code.
|
||||
*/
|
||||
ERRCODE parse(istringstream *roStream);
|
||||
|
||||
/**
|
||||
* Check the permission of the content.
|
||||
* @param type the operation type.
|
||||
* @param contentID the specific contentID.
|
||||
* @return true/false to indicate result.
|
||||
*/
|
||||
bool checkPermission(OperationPermission::OPERATION type,
|
||||
const string& contentID);
|
||||
|
||||
/**
|
||||
* Consume the right related to content.
|
||||
* @param type the operation type.
|
||||
* @param contentID the specific contentID.
|
||||
* @return the status of consume.
|
||||
*/
|
||||
ERRCODE consume(OperationPermission::OPERATION type,
|
||||
const string& contentID);
|
||||
|
||||
/**
|
||||
* Get CEK of content.
|
||||
* @param contentID the specific content id.
|
||||
* @return "" if not found otherwise return CEK.
|
||||
*/
|
||||
string getContentCek(const string& contentID);
|
||||
|
||||
/**
|
||||
* Get Digest value of content.
|
||||
* @param contentID the specific content id.
|
||||
* @return "" if not found otherwise return digest value.
|
||||
*/
|
||||
string getContentHash(const string& contentID);
|
||||
|
||||
PRIVATE:
|
||||
/**
|
||||
* Handle the xml dom document.
|
||||
* @param doc the pointer to the dom document.
|
||||
* @return true/false to indicate the result.
|
||||
*/
|
||||
bool handleDocument(const XMLDocumentImpl* doc);
|
||||
|
||||
/**
|
||||
* Handle the xml dom node which contains <right> element.
|
||||
* @param curNode the dom node which contains <right> element.
|
||||
* @return true/false to indicate the result.
|
||||
*/
|
||||
bool handleRights(const NodeImpl *curNode);
|
||||
|
||||
/**
|
||||
* Handle the xml dom node which contains the <agreement> element.
|
||||
* @param curNode the dom node which contains <agreement> element.
|
||||
* @return true/false to indicate the result.
|
||||
*/
|
||||
bool handleAgreement(const NodeImpl *curNode);
|
||||
|
||||
/**
|
||||
* Handle the xml dom node which contains the <asset> element.
|
||||
* @param curNode the dom node which contains <asset> element.
|
||||
* @return true/false to indicate the result.
|
||||
*/
|
||||
bool handleAsset(const NodeImpl *curNode);
|
||||
|
||||
/**
|
||||
* Handle the xml dom node which contains the <permission> element.
|
||||
* @param curNode the dom node which contains <permission> element.
|
||||
* @return true/false to indicate the result.
|
||||
*/
|
||||
bool handlePermission(const NodeImpl *curNode);
|
||||
|
||||
/**
|
||||
* Get the constraint in xml dom node.
|
||||
* @param curNode the dom node which contains constraint.
|
||||
* @return the constraint.
|
||||
*/
|
||||
Constraint* getConstraint(const NodeImpl *curNode);
|
||||
|
||||
/**
|
||||
* Convert ISO8601 time to long.
|
||||
* @param ts the string with ISO8601 time.
|
||||
* @return the result value.
|
||||
*/
|
||||
long convertISO8601DateTimeToLong(const char* ts);
|
||||
|
||||
/**
|
||||
* Convert ISO8601 period to long.
|
||||
* @param ts the string with ISO8601 period.
|
||||
* @return the result value.
|
||||
*/
|
||||
long convertISO8601PeriodToLong(const char* ts);
|
||||
|
||||
/**
|
||||
* Load the rights related with specific contentinto content rights list.
|
||||
* @param contentID the specific content id.
|
||||
*/
|
||||
void loadRights(const string& contentID);
|
||||
|
||||
/**
|
||||
* Free the current content rights list.
|
||||
*/
|
||||
void freeRights();
|
||||
|
||||
PRIVATE:
|
||||
/**
|
||||
* Disable the assignment between rights.
|
||||
*/
|
||||
Ro& operator=(const Ro& ro);
|
||||
|
||||
/**
|
||||
* Disable copy constructor.
|
||||
*/
|
||||
Ro(const Ro& ro);
|
||||
|
||||
public:
|
||||
vector<Asset*> mAssetList;
|
||||
vector<Right*> mRightList;
|
||||
|
||||
PRIVATE:
|
||||
string mRoID; /** the Ro id. */
|
||||
string mRoVersion; /** the Ro version. */
|
||||
XMLDocumentImpl *mDoc; /**< the xml document handle. */
|
||||
vector<Right*> mContentRightList; /**< the right list to store the result related with specific content. */
|
||||
Right* mProperRight; /**< the right to consume. */
|
||||
};
|
||||
#endif
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _ROMANAGER_H
|
||||
#define _ROMANAGER_H
|
||||
|
||||
#include <Drm2CommonTypes.h>
|
||||
#include <ustring.h>
|
||||
#include <rights/Ro.h>
|
||||
|
||||
using namespace ustl;
|
||||
|
||||
class RoManager {
|
||||
|
||||
public:
|
||||
/**
|
||||
* Singleton instance function.
|
||||
* @return the singleton pointer.
|
||||
*/
|
||||
static RoManager* Instance();
|
||||
|
||||
/**
|
||||
* Destructor for ExpatWrapper.
|
||||
*/
|
||||
~RoManager();
|
||||
|
||||
/**
|
||||
* Install Ro from stream.
|
||||
* @param roStream the input ro stream.
|
||||
* @return the status of installaltion.
|
||||
*/
|
||||
Ro::ERRCODE installRo(istringstream *roStream);
|
||||
|
||||
/**
|
||||
* Check whether Ro in cache or not.
|
||||
* @param roID the specific roID.
|
||||
* @return true/false to indicate result.
|
||||
*/
|
||||
bool checkRoInCache(const string& roID);
|
||||
|
||||
/**
|
||||
* Get the ro.
|
||||
* @param roID the specific id of ro.
|
||||
* @return NULL if not found otherwise return ro.
|
||||
*/
|
||||
Ro* getRo(const string& roID);
|
||||
|
||||
/**
|
||||
* Get all the Ro.
|
||||
* @return ro list.
|
||||
*/
|
||||
vector<Ro*> getAllRo();
|
||||
|
||||
/**
|
||||
* Get ro which contained rights of specific content.
|
||||
* @param contentID the specific id of content.
|
||||
* @return NULL if not fount otherwise the related ro.
|
||||
*/
|
||||
Ro* getRoByContentID(const string& contentID);
|
||||
|
||||
/**
|
||||
* Delete Ro by its id.
|
||||
* @param roID the specific roID.
|
||||
* @return true/false to indicate the result.
|
||||
*/
|
||||
bool deleteRo(const string& roID);
|
||||
|
||||
|
||||
PRIVATE:
|
||||
/**
|
||||
* Constructor for RoManager.
|
||||
*/
|
||||
RoManager();
|
||||
|
||||
PRIVATE:
|
||||
static RoManager* msInstance; /**< singleton instance pointer. */
|
||||
vector<Ro*> mRoList; /**< the ro list. */
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _REGISTRATION_
|
||||
#define _REGISTRATION_
|
||||
|
||||
#include <roap/RoapMessageHandler.h>
|
||||
|
||||
class Registration : public RoapMessageHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor for Registration.
|
||||
* @param type the address of RI.
|
||||
*/
|
||||
Registration(string riAddres);
|
||||
|
||||
/**
|
||||
* Registration with the RI.
|
||||
* @return the result of registration.
|
||||
*/
|
||||
int16_t registerWithRI();
|
||||
|
||||
/**
|
||||
* Create one specified client message based on message template xml file.
|
||||
* @param type the message type.
|
||||
* @return the pointer of the document object of the message if successful,otherwise
|
||||
* return NULL.
|
||||
*/
|
||||
XMLDocumentImpl* createClientMsg(int16_t type);
|
||||
}
|
||||
#endif _REGISTRATION_
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _ROAPMESSAGEHADLER_
|
||||
#define _ROAPMESSAGEHADLER_
|
||||
|
||||
#include <Drm2CommonTypes.h>
|
||||
#include <util/xml/XMLDocumentImpl.h>
|
||||
|
||||
class RoapMessageHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* define all the client message types.
|
||||
*/
|
||||
enum msgType {DeviceHello=1,RegistrationRequest,RORequest};
|
||||
|
||||
/**
|
||||
* Constructor for DrmManager,used to open local dcf file.
|
||||
* @param type the message type.
|
||||
*/
|
||||
RoapMessageHandler();
|
||||
|
||||
/**
|
||||
* Create one specified client message based on message template xml file.
|
||||
* @param type the message type.
|
||||
* @return the pointer of the document object of the message if successful,otherwise
|
||||
* return NULL.
|
||||
*/
|
||||
XMLDocumentImpl* createClientMsg(msgType type);
|
||||
|
||||
/**
|
||||
* Handle received message from RI.
|
||||
* @return true if successful, otherwise return false.
|
||||
*/
|
||||
bool handlePeerMsg();
|
||||
|
||||
/**
|
||||
* Send the client message to RI
|
||||
*/
|
||||
int16_t send();
|
||||
|
||||
/**
|
||||
* Receive message from RI and parse it
|
||||
* @return the pointer of the parsed document.
|
||||
*/
|
||||
XMLDocumentImpl* receive();
|
||||
|
||||
PROTECTED:
|
||||
XMLDocumentImpl * mDoc;
|
||||
PRIVATE:
|
||||
int16_t mMsgType;
|
||||
};
|
||||
#endif //_ROAPMESSAGEHADLER_
|
||||
@@ -1,211 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _DRMCRYPTO_H_
|
||||
#define _DRMCRYPTO_H_
|
||||
|
||||
#include <Drm2CommonTypes.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
// AES encrypt mode
|
||||
typedef enum {AES_128_CBC = 0x01,AES_128_CTR = 0x02}AesMode;
|
||||
|
||||
// aes crypto for decrypt
|
||||
class AesAgent
|
||||
{
|
||||
public:
|
||||
AesAgent(const AesMode method,const unsigned char* decryptedKey)
|
||||
:mode(method),AesKey(decryptedKey){};
|
||||
|
||||
/**
|
||||
* decrypt data using AES, now only support 128 bits CBC
|
||||
* \param iv 128 bits initialization vector/counter
|
||||
* prefixing the ciphertext
|
||||
* \param encData encrypted data
|
||||
* \param encLen the length of encData
|
||||
* \param decData the buffer to store decrypted data
|
||||
* \param decLen the actual length of decrypted data
|
||||
* \return
|
||||
* >= succeed, the padding length
|
||||
* < 0 failed
|
||||
*/
|
||||
int32_t decContent( unsigned char* iv,
|
||||
const unsigned char* encData,
|
||||
const unsigned long encLen,
|
||||
unsigned char* decData);
|
||||
static const int32_t AES_DEC_FAILED = -1;
|
||||
|
||||
PRIVATE:
|
||||
static const uint32_t AES_KEY_BITS = 128;
|
||||
const AesMode mode;
|
||||
const unsigned char* AesKey;
|
||||
|
||||
PRIVATE:
|
||||
// get the actual length of decrypt data
|
||||
void discardPaddingByte(unsigned char* decryptedBuf,unsigned long* decryptedBufLen);
|
||||
};
|
||||
|
||||
// Sha1 crypto for hash
|
||||
class Sha1Agent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* compute hash using Sha1
|
||||
* \param inData the data to be hashed
|
||||
* \param inLen the length of inData
|
||||
* \param outHash the hash of inData
|
||||
* \return none
|
||||
*/
|
||||
void computeHash( const unsigned char* inData,
|
||||
unsigned long inLen,
|
||||
unsigned char* outHash) const;
|
||||
|
||||
/**
|
||||
* get the length of SHA1 hash
|
||||
* \param none
|
||||
* \return
|
||||
* the length of SHA1 hash
|
||||
*/
|
||||
unsigned long getShaLen(void) const
|
||||
{
|
||||
return SHA_DIGEST_LENGTH;
|
||||
}
|
||||
};
|
||||
|
||||
// Hmac-Sha1 crypto for MAC
|
||||
class HmacSha1Agent
|
||||
{
|
||||
public:
|
||||
HmacSha1Agent(const unsigned char* Key, int key_len)
|
||||
:macKey(Key),keyLen(key_len){};
|
||||
|
||||
/**
|
||||
* compute MAC using Hmac-Sha1
|
||||
* \param inData the data to be MAC
|
||||
* \param inLen the length of inData
|
||||
* \param outMac the MAC of inData
|
||||
* \return none
|
||||
*/
|
||||
void computeMac( const unsigned char* inData,
|
||||
unsigned long inLen,
|
||||
unsigned char* outMac) const;
|
||||
|
||||
/**
|
||||
* get the length of HMAC-SHA1 MAC
|
||||
* \param none
|
||||
* \return
|
||||
* the length of HMAC-SHA1 MAC
|
||||
*/
|
||||
unsigned long getHmacLen(void) const
|
||||
{
|
||||
return SHA_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
PRIVATE:
|
||||
const unsigned char* macKey;
|
||||
const int keyLen;
|
||||
};
|
||||
|
||||
// Rsa crypto for signature,verify signature and key transport
|
||||
class RsaAgent
|
||||
{
|
||||
public:
|
||||
RsaAgent(RSA& Key):rsaKey(Key)
|
||||
{
|
||||
rsaSize = (unsigned int)RSA_size(&Key);
|
||||
};
|
||||
|
||||
// signature algorithm
|
||||
typedef enum {RSA_PSS,RSA_SHA1}RsaAlg;
|
||||
|
||||
/**
|
||||
* Do signature using RSA-PSS
|
||||
* \param rawData the data to be signature
|
||||
* \param rawLen the length of inData
|
||||
* \param sigData the buffer to store the signature of rawData
|
||||
* \param sigAlg signature algorithm
|
||||
* \return
|
||||
* true succeed
|
||||
* false failed
|
||||
*/
|
||||
bool signature( const unsigned char* rawData,
|
||||
const unsigned long rawLen,
|
||||
unsigned char* sigData,
|
||||
const RsaAlg sigAlg);
|
||||
|
||||
/**
|
||||
* get the length of signature
|
||||
* \param none
|
||||
* \return
|
||||
* the length of signature
|
||||
*/
|
||||
unsigned int getSigLen(void) const
|
||||
{
|
||||
return rsaSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify signature using RSA-PSS
|
||||
* \param sigData the data to be verify
|
||||
* \param sigLen the length of sigData
|
||||
* \param rawData the data from which the sigData generated
|
||||
* \param rawLen the length of rawData
|
||||
* \param sigAlg signature algorithm
|
||||
* \return
|
||||
* true succeed
|
||||
* false failed
|
||||
*/
|
||||
bool sigVerify(unsigned char* sigData,
|
||||
unsigned long sigLen,
|
||||
const unsigned char* rawData,
|
||||
const unsigned long rawLen,
|
||||
const RsaAlg sigAlg);
|
||||
|
||||
|
||||
/**
|
||||
* Decrypt data using RSA
|
||||
* \param encData encrypted data
|
||||
* \param encLen the length of encData
|
||||
* \param decData the buffer to store decrypted data
|
||||
* \return
|
||||
* -1 decrypted failed
|
||||
* >0 the actual length of decrypted data
|
||||
*/
|
||||
int decrypt( const unsigned char* encData,
|
||||
const unsigned long encLen,
|
||||
unsigned char* decData);
|
||||
|
||||
/**
|
||||
* get the length of decrypted data
|
||||
* \param none
|
||||
* \return
|
||||
* the length of decrypted data
|
||||
*/
|
||||
unsigned int getDecLen(void) const
|
||||
{
|
||||
return rsaSize;
|
||||
}
|
||||
|
||||
PRIVATE:
|
||||
RSA& rsaKey;
|
||||
unsigned int rsaSize;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _DRMCRYPTO_H_ */
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __CHARACTER_IMPL__
|
||||
#define __CHARACTER_IMPL__
|
||||
|
||||
#include "NodeImpl.h"
|
||||
#include "DOMString.h"
|
||||
|
||||
class CharacterDataImpl : public NodeImpl
|
||||
{
|
||||
private:
|
||||
DOMString* charData;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default Constructor for CharacterDataImpl.
|
||||
*/
|
||||
CharacterDataImpl();
|
||||
|
||||
/**
|
||||
* Constructor for CharacterDataImpl.
|
||||
* @param data The specify character data.
|
||||
*/
|
||||
CharacterDataImpl(const DOMString* data);
|
||||
|
||||
/**
|
||||
* The character data of the node that implements this interface. The DOM
|
||||
* implementation may not put arbitrary limits on the amount of data
|
||||
* that may be stored in a <code>CharacterData</code> node. However,
|
||||
* implementation limits may mean that the entirety of a node's data may
|
||||
* not fit into a single <code>DOMString</code>. In such cases, the user
|
||||
* may call <code>substringData</code> to retrieve the data in
|
||||
* appropriately sized pieces.
|
||||
* @exception DOMException
|
||||
* NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
|
||||
* @exception DOMException
|
||||
* DOMSTRING_SIZE_ERR: Raised when it would return more characters than
|
||||
* fit in a <code>DOMString</code> variable on the implementation
|
||||
* platform.
|
||||
* @return the character data.
|
||||
*/
|
||||
const DOMString* getData() const throw (DOMException);
|
||||
|
||||
/**
|
||||
* The character data of the node that implements this interface. The DOM
|
||||
* implementation may not put arbitrary limits on the amount of data
|
||||
* that may be stored in a <code>CharacterData</code> node. However,
|
||||
* implementation limits may mean that the entirety of a node's data may
|
||||
* not fit into a single <code>DOMString</code>. In such cases, the user
|
||||
* may call <code>substringData</code> to retrieve the data in
|
||||
* appropriately sized pieces.
|
||||
* @param data the specify character data.
|
||||
* @exception DOMException
|
||||
* NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
|
||||
* @exception DOMException
|
||||
* DOMSTRING_SIZE_ERR: Raised when it would return more characters than
|
||||
* fit in a <code>DOMString</code> variable on the implementation
|
||||
* platform.
|
||||
*/
|
||||
void setData(const DOMString* data) throw (DOMException);
|
||||
|
||||
/**
|
||||
* The number of 16-bit units that are available through <code>data</code>
|
||||
* and the <code>substringData</code> method below. This may have the
|
||||
* value zero, i.e., <code>CharacterData</code> nodes may be empty.
|
||||
* @return the size of characters data.
|
||||
*/
|
||||
int getLength() const;
|
||||
|
||||
/**
|
||||
* Append the string to the end of the character data of the node. Upon
|
||||
* success, <code>data</code> provides access to the concatenation of
|
||||
* <code>data</code> and the <code>DOMString</code> specified.
|
||||
* @param arg The <code>DOMString</code> to append.
|
||||
* @exception DOMException
|
||||
* NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
|
||||
*/
|
||||
void appendData(const DOMString* arg) throw(DOMException);
|
||||
|
||||
/** Override getNodeValue() method in NodeImpl.h.*/
|
||||
const DOMString* getNodeValue() const throw(DOMException);
|
||||
|
||||
/** Override setNodeValue() method in NodeImpl.h */
|
||||
void setNodeValue(DOMString* nodeValue) throw(DOMException);
|
||||
|
||||
~CharacterDataImpl();
|
||||
};
|
||||
#endif /*__CHARACTER_IMPL__*/
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __DOM_EXCEPTION__
|
||||
#define __DOM_EXCEPTION__
|
||||
|
||||
#include <uexception.h>
|
||||
using namespace ustl;
|
||||
|
||||
/**
|
||||
* DOM operations only raise exceptions in "exceptional" circumstances, i.e.,
|
||||
* when an operation is impossible to perform (either for logical reasons, because data is lost,
|
||||
* or because the implementation has become unstable). In general, DOM methods return specific error
|
||||
* values in ordinary processing situations, such as out-of-bound errors when using <code>NodeList</code>.
|
||||
* <p>Implementations should raise other exceptions under other circumstances. For example, implementations
|
||||
* should raise an implementation-dependent exception if a null argument is passed.
|
||||
* Some languages and object systems do not support the concept of exceptions.
|
||||
* For such systems, error conditions may be indicated using native error reporting mechanisms.
|
||||
* For some bindings, for example, methods may return error codes similar to those listed in the corresponding
|
||||
* method descriptions.
|
||||
*/
|
||||
class DOMException : public exception {
|
||||
|
||||
private:
|
||||
short code;
|
||||
public:
|
||||
DOMException(short code)
|
||||
{
|
||||
this->code = code;
|
||||
}
|
||||
public:
|
||||
|
||||
enum ExceptionReason {
|
||||
/**
|
||||
* If index or size is negative, or greater than the allowed value
|
||||
*/
|
||||
INDEX_SIZE_ERR = 1,
|
||||
|
||||
/**
|
||||
* If the specified range of text does not fit into a DOMString
|
||||
* @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html
|
||||
*/
|
||||
DOMSTRING_SIZE_ERR = 2,
|
||||
/**
|
||||
* If any node is inserted somewhere it doesn't belong
|
||||
* @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html
|
||||
*/
|
||||
HIERARCHY_REQUEST_ERR = 3,
|
||||
|
||||
/**
|
||||
* If a node is used in a different document than the one that created it
|
||||
* (that doesn't support it)
|
||||
* @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html
|
||||
*/
|
||||
WRONG_DOCUMENT_ERR = 4,
|
||||
|
||||
/**
|
||||
* If an invalid or illegal character is specified, such as in a name. See
|
||||
* production 2 in the XML specification for the definition of a legal
|
||||
* character, and production 5 for the definition of a legal name
|
||||
* character.
|
||||
* @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html
|
||||
*/
|
||||
INVALID_CHARACTER_ERR = 5,
|
||||
|
||||
/**
|
||||
* If data is specified for a node which does not support data
|
||||
* @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html
|
||||
*/
|
||||
NO_DATA_ALLOWED_ERR = 6,
|
||||
|
||||
/**
|
||||
* If an attempt is made to modify an object where modifications are not
|
||||
* allowed
|
||||
* @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html
|
||||
*/
|
||||
NO_MODIFICATION_ALLOWED_ERR = 7,
|
||||
|
||||
/**
|
||||
* If an attempt is made to reference a node in a context where it does
|
||||
* not exist
|
||||
* @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html
|
||||
*/
|
||||
NOT_FOUND_ERR = 8,
|
||||
|
||||
/**
|
||||
* If the implementation does not support the requested type of object or
|
||||
* operation.
|
||||
* @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html
|
||||
*/
|
||||
NOT_SUPPORTED_ERR = 9,
|
||||
|
||||
/**
|
||||
* If an attempt is made to add an attribute that is already in use
|
||||
* elsewhere
|
||||
*/
|
||||
INUSE_ATTRIBUTE_ERR = 10,
|
||||
|
||||
/**
|
||||
* If an attempt is made to use an object that is not, or is no longer,
|
||||
* usable.
|
||||
* @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html
|
||||
*/
|
||||
INVALID_STATE_ERR = 11,
|
||||
|
||||
/**
|
||||
* If an invalid or illegal string is specified.
|
||||
* @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html
|
||||
*/
|
||||
SYNTAX_ERR = 12,
|
||||
|
||||
/**
|
||||
* If an attempt is made to modify the type of the underlying object.
|
||||
* @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html
|
||||
*/
|
||||
INVALID_MODIFICATION_ERR = 13,
|
||||
|
||||
/**
|
||||
* If an attempt is made to create or change an object in a way which is
|
||||
* incorrect with regard to namespaces.
|
||||
* @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html
|
||||
*/
|
||||
NAMESPACE_ERR = 14,
|
||||
|
||||
/**
|
||||
* If a parameter or an operation is not supported by the underlying
|
||||
* object.
|
||||
* @since http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html
|
||||
*/
|
||||
INVALID_ACCESS_ERR = 15,
|
||||
};
|
||||
public:
|
||||
/**
|
||||
* Return the exception reason.
|
||||
* @return the exception reason.
|
||||
*/
|
||||
short getCode() const
|
||||
{
|
||||
return code;
|
||||
}
|
||||
};
|
||||
#endif /*__DOMEXCEPTION__*/
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __DOM_STRING_H__
|
||||
#define __DOM_STRING_H__
|
||||
|
||||
#include <ustring.h>
|
||||
using namespace ustl;
|
||||
typedef string DOMString;
|
||||
|
||||
const DOMString emptyString = DOMString("");
|
||||
|
||||
#endif /*__DOM_STRING_H_*/
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __DOM_DOCUMENT_IMPL__
|
||||
#define __DOM_DOCUMENT_IMPL__
|
||||
#include "DOMString.h"
|
||||
#include "NodeImpl.h"
|
||||
#include "ElementImpl.h"
|
||||
#include "NodeType.h"
|
||||
#include "TextImpl.h"
|
||||
#include "NodeListImpl.h"
|
||||
#include "DOMException.h"
|
||||
|
||||
class DocumentImpl : public NodeImpl
|
||||
{
|
||||
private:
|
||||
const static DOMString nodeName;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default constructor for DocumentImpl.
|
||||
*/
|
||||
DocumentImpl();
|
||||
/**
|
||||
* This is a convenience attribute that allows direct access to the child
|
||||
* node that is the root element of the document. For HTML documents,
|
||||
* this is the element with the tagName "HTML".
|
||||
* @return the pointer to element.
|
||||
*/
|
||||
virtual ElementImpl* getDocumentElement() const;
|
||||
|
||||
/**
|
||||
* Creates an element of the type specified. Note that the instance
|
||||
* returned implements the <code>Element</code> interface, so attributes
|
||||
* can be specified directly on the returned object.
|
||||
* <br>In addition, if there are known attributes with default values,
|
||||
* <code>Attr</code> nodes representing them are automatically created
|
||||
* and attached to the element.
|
||||
* <br>To create an element with a qualified name and namespace URI, use
|
||||
* the <code>createElementNS</code> method.
|
||||
* @param tagName The name of the element type to instantiate. For XML,
|
||||
* this is case-sensitive. For HTML, the <code>tagName</code>
|
||||
* parameter may be provided in any case, but it must be mapped to the
|
||||
* canonical uppercase form by the DOM implementation.
|
||||
* @return A new <code>Element</code> object with the
|
||||
* <code>nodeName</code> attribute set to <code>tagName</code>, and
|
||||
* <code>localName</code>, <code>prefix</code>, and
|
||||
* <code>namespaceURI</code> set to <code>null</code>.
|
||||
* @exception DOMException
|
||||
* INVALID_CHARACTER_ERR: Raised if the specified name contains an
|
||||
* illegal character.
|
||||
*/
|
||||
virtual ElementImpl* createElement(const DOMString* tagName) const throw (DOMException);
|
||||
|
||||
/**
|
||||
* Creates a <code>Text</code> node given the specified string.
|
||||
* @param data The data for the node.
|
||||
* @return The new <code>Text</code> object.
|
||||
*/
|
||||
virtual TextImpl* createTextNode(const DOMString* data) const;
|
||||
|
||||
/**
|
||||
* Returns a <code>NodeList</code> of all the <code>Elements</code> with a
|
||||
* given tag name in the order in which they are encountered in a
|
||||
* preorder traversal of the <code>Document</code> tree.
|
||||
* @param tagname The name of the tag to match on. The special value "*"
|
||||
* matches all tags.
|
||||
* @return A new <code>NodeList</code> object containing all the matched
|
||||
* <code>Elements</code>.
|
||||
*/
|
||||
NodeListImpl* getElementsByTagName(const DOMString* tagname) const;
|
||||
|
||||
/** Override getNodeName method in NodeImpl.h.*/
|
||||
const DOMString* getNodeName() const;
|
||||
|
||||
/** Override getNodeType method in NodeImpl.h.*/
|
||||
NodeType getNodeType() const;
|
||||
|
||||
/**
|
||||
*
|
||||
* Event Triggered after loaded the document.
|
||||
*/
|
||||
virtual bool onLoad(){return true;}
|
||||
|
||||
/**
|
||||
*
|
||||
* Event Triggered when close or switch the document.
|
||||
*/
|
||||
virtual bool onUnLoad(){return true;}
|
||||
|
||||
~DocumentImpl();
|
||||
};
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __DOM_ELEMENT_IMPL__
|
||||
#define __DOM_ELEMENT_IMPL__
|
||||
#include "NodeImpl.h"
|
||||
#include "NodeListImpl.h"
|
||||
#include "NodeType.h"
|
||||
|
||||
class ElementImpl : public NodeImpl
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* The name of the element. For example, in:
|
||||
* <pre> <elementExample
|
||||
* id="demo"> ... </elementExample> , </pre>
|
||||
* <code>tagName</code> has
|
||||
* the value <code>"elementExample"</code>. Note that this is
|
||||
* case-preserving in XML, as are all of the operations of the DOM. The
|
||||
* HTML DOM returns the <code>tagName</code> of an HTML element in the
|
||||
* canonical uppercase form, regardless of the case in the source HTML
|
||||
* document.
|
||||
* @return the element's tag name.
|
||||
*/
|
||||
virtual const DOMString* getTagName() const;
|
||||
|
||||
/**
|
||||
* Retrieves an attribute value by name.
|
||||
* @param name The name of the attribute to retrieve.
|
||||
* @return The <code>Attr</code> value as a string, or the empty string
|
||||
* if that attribute does not have a specified or default value.
|
||||
*/
|
||||
virtual const DOMString* getAttribute(const DOMString* name) const;
|
||||
|
||||
/**
|
||||
* Adds a new attribute. If an attribute with that name is already present
|
||||
* in the element, its value is changed to be that of the value
|
||||
* parameter. This value is a simple string; it is not parsed as it is
|
||||
* being set. So any markup (such as syntax to be recognized as an
|
||||
* entity reference) is treated as literal text, and needs to be
|
||||
* appropriately escaped by the implementation when it is written out.
|
||||
* In order to assign an attribute value that contains entity
|
||||
* references, the user must create an <code>Attr</code> node plus any
|
||||
* <code>Text</code> and <code>EntityReference</code> nodes, build the
|
||||
* appropriate subtree, and use <code>setAttributeNode</code> to assign
|
||||
* it as the value of an attribute.
|
||||
* <br>To set an attribute with a qualified name and namespace URI, use
|
||||
* the <code>setAttributeNS</code> method.
|
||||
* @param name The name of the attribute to create or alter.
|
||||
* @param value Value to set in string form.
|
||||
* @exception DOMException
|
||||
* INVALID_CHARACTER_ERR: Raised if the specified name contains an
|
||||
* illegal character.
|
||||
* <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
|
||||
*/
|
||||
virtual void setAttribute(const DOMString* name, const DOMString* value) throw (DOMException);
|
||||
|
||||
/**
|
||||
* Removes an attribute by name. If the removed attribute is known to have
|
||||
* a default value, an attribute immediately appears containing the
|
||||
* default value as well as the corresponding namespace URI, local name,
|
||||
* and prefix when applicable.
|
||||
* <br>To remove an attribute by local name and namespace URI, use the
|
||||
* <code>removeAttributeNS</code> method.
|
||||
* @param name The name of the attribute to remove.
|
||||
* @exception DOMException
|
||||
* NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
|
||||
*/
|
||||
virtual void removeAttribute(const DOMString* name) throw (DOMException);
|
||||
|
||||
/**
|
||||
* Returns a <code>NodeList</code> of all descendant <code>Elements</code>
|
||||
* with a given tag name, in the order in which they are encountered in
|
||||
* a preorder traversal of this <code>Element</code> tree.
|
||||
* @param name The name of the tag to match on. The special value "*"
|
||||
* matches all tags.
|
||||
* @return A list of matching <code>Element</code> nodes.
|
||||
*/
|
||||
NodeListImpl* getElementsByTagName(const DOMString* name) const;
|
||||
|
||||
/** Override getNodeType() method in NodeImpl.h.*/
|
||||
virtual bool hasAttributes() const;
|
||||
|
||||
/** Override getNodeName() method in NodeImpl.h.*/
|
||||
const DOMString* getNodeName() const;
|
||||
|
||||
/** Override getNodeType() method in NodeImpl.h.*/
|
||||
NodeType getNodeType() const;
|
||||
|
||||
/** Defining "click()" method*/
|
||||
virtual void click(){}
|
||||
|
||||
/** Defining "blur()" method,*/
|
||||
virtual void blur(){}
|
||||
|
||||
/** Defining "focus()" method*/
|
||||
virtual void focus(){}
|
||||
|
||||
/** Defining "change()" method*/
|
||||
virtual void change(){}
|
||||
|
||||
/** Defining "select()" method*/
|
||||
virtual void select(){}
|
||||
|
||||
/** Defining "onClick()" event input,textarea,button, and anchor*/
|
||||
virtual bool onClick(){return true;}
|
||||
|
||||
/** Defining "onBlur()" event,for input,textarea,button,anchor and select */
|
||||
virtual bool onBlur(){return true;}
|
||||
|
||||
/** Defining "onFocus()" event,for input,textarea,button,anchor and select*/
|
||||
virtual bool onFocus(){return true;}
|
||||
|
||||
/** Defining "onChange()" event,for input,textarea and select tag*/
|
||||
virtual bool onChange(){return true;}
|
||||
|
||||
/** Defining "onSelect()" event,for textarea and input*/
|
||||
virtual bool onSelect(){return true;}
|
||||
|
||||
/**
|
||||
* when the end tag of one element is found,this method would be called.The basic action is call seCompleted().
|
||||
**/
|
||||
virtual void endElement() {}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Get elements whose name match on <code>name</code>,than keep they into <code>nodeList</code>.
|
||||
* @param name The tag name of the elements to match on.
|
||||
* @param nodeList keep all the matched element.
|
||||
*/
|
||||
void getElementsByTagName(const DOMString* name,NodeListImpl* nodeList) const;
|
||||
};
|
||||
#endif /*__DOM_ELEMENT_IMPL__*/
|
||||
|
||||
@@ -1,266 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __DOM_NODE_IMPL__
|
||||
#define __DOM_NODE_IMPL__
|
||||
|
||||
#include "DOMException.h"
|
||||
#include "NodeType.h"
|
||||
#include "DOMString.h"
|
||||
class LayoutAttr;
|
||||
class DocumentImpl;
|
||||
class NodeImpl {
|
||||
private:
|
||||
/** The pointer to first children */
|
||||
NodeImpl* firstChild;
|
||||
|
||||
/** The pointer to lastChild children */
|
||||
NodeImpl* lastChild;
|
||||
|
||||
/** The pointer to previous sibling children */
|
||||
NodeImpl* previousSibling;
|
||||
|
||||
/** The pointer to next sibling children */
|
||||
NodeImpl* nextSibling;
|
||||
|
||||
/** The pointer to parent */
|
||||
NodeImpl* parent;
|
||||
|
||||
/** Current node's document context */
|
||||
const DocumentImpl* document;
|
||||
|
||||
/**
|
||||
* Add next slibing node
|
||||
* @param node the node to be add.
|
||||
*/
|
||||
void appendNextSibling(NodeImpl* node);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default constuctor.
|
||||
*/
|
||||
NodeImpl(): firstChild(NULL),lastChild(NULL),previousSibling(NULL),nextSibling(NULL),parent(NULL),document(NULL) {};
|
||||
|
||||
/**
|
||||
* Set <code>parentNode</code> as current node's parent.
|
||||
*
|
||||
* @param parentNode The specify parent node.
|
||||
*/
|
||||
void setParent(NodeImpl* parentNode);
|
||||
|
||||
/**
|
||||
* Set the node immediately following node.
|
||||
*
|
||||
* @param siblingNode The special node be insert after current node.
|
||||
*/
|
||||
void setNextSibling(NodeImpl* siblingNode);
|
||||
|
||||
/**
|
||||
* Returns the node immediately preceding this node.
|
||||
*
|
||||
* @param siblingNode The special node be insert before current node.
|
||||
*/
|
||||
void setPreviousSibling(NodeImpl* siblingNode);
|
||||
|
||||
/**
|
||||
* Set <code>childNode</code> as current node's first children. If current
|
||||
* node have first child node,it will replace with the <code>childNode</code>.
|
||||
*
|
||||
* @param childNode The special node be set as the first children node of current
|
||||
* node.
|
||||
*/
|
||||
void setFirstChild(NodeImpl* childNode);
|
||||
|
||||
/**
|
||||
* Set <code>childNode</code> as current node's last children. If current
|
||||
* node have last child node,it will replace with the <code>childNode</code>.
|
||||
*
|
||||
* @param childNode The special node be set as the last children node of current
|
||||
* node.
|
||||
*/
|
||||
void setLastChild(NodeImpl* childNode);
|
||||
|
||||
/**
|
||||
* The name of this node, depending on its type;
|
||||
* @return the node's name.
|
||||
*/
|
||||
virtual const DOMString* getNodeName() const = 0;
|
||||
|
||||
/**
|
||||
* The value of this node, depending on its type;
|
||||
* When it is defined to be <code>null</code>, setting it has no effect.
|
||||
* @return the value of node.
|
||||
* @exception DOMException
|
||||
* DOMSTRING_SIZE_ERR: Raised when it would return more characters than
|
||||
* fit in a <code>DOMString</code> variable on the implementation
|
||||
* platform.
|
||||
*/
|
||||
virtual const DOMString* getNodeValue() const throw (DOMException);
|
||||
|
||||
/**
|
||||
* Set the node value.
|
||||
* @param nodeValue the node value
|
||||
* @exception DOMException
|
||||
* NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
|
||||
*/
|
||||
virtual void setNodeValue(DOMString* nodeValue) throw (DOMException);
|
||||
|
||||
/**
|
||||
* A code representing the type of the underlying object, as defined above.
|
||||
* @return the node's type.
|
||||
*/
|
||||
virtual NodeType getNodeType() const = 0;
|
||||
|
||||
/**
|
||||
* Returns whether this node (if it is an element) has any attributes.
|
||||
* @return <code>true</code> if this node has any attributes,
|
||||
* <code>false</code> otherwise.
|
||||
* @since DOM Level 2
|
||||
*/
|
||||
virtual bool hasAttributes() const;
|
||||
|
||||
/**
|
||||
* The parent of this node. All nodes, except <code>Attr</code>,
|
||||
* <code>Document</code>, <code>DocumentFragment</code>,
|
||||
* <code>Entity</code>, and <code>Notation</code> may have a parent.
|
||||
* However, if a node has just been created and not yet added to the
|
||||
* tree, or if it has been removed from the tree, this is
|
||||
* <code>NULL</code>.
|
||||
* @return return current node's parent.
|
||||
*/
|
||||
NodeImpl* getParentNode() const;
|
||||
|
||||
/**
|
||||
* The first child of this node. If there is no such node, this returns
|
||||
* <code>NULL</code>.
|
||||
* @return current node first children.
|
||||
*/
|
||||
NodeImpl* getFirstChild() const;
|
||||
|
||||
/**
|
||||
* The last child of this node. If there is no such node, this returns
|
||||
* <code>NULL</code>.
|
||||
* @return current node last children.
|
||||
*/
|
||||
NodeImpl* getLastChild() const;
|
||||
|
||||
/**
|
||||
* The node immediately preceding this node. If there is no such node,
|
||||
* this returns <code>NULL</code>.
|
||||
* @return current node previous sibling children.
|
||||
*/
|
||||
NodeImpl* getPreviousSibling() const;
|
||||
|
||||
/**
|
||||
* The node immediately following this node. If there is no such node,
|
||||
* this returns <code>NULL</code>.
|
||||
* @return return current node next sibling children.
|
||||
*/
|
||||
NodeImpl* getNextSibling() const;
|
||||
|
||||
/**
|
||||
* Inserts the node <code>newChild</code> before the existing child node
|
||||
* <code>refChild</code>. If <code>refChild</code> is <code>NULL</code>,
|
||||
* insert <code>newChild</code> at the end of the list of children.
|
||||
* <br>If <code>newChild</code> is a <code>DocumentFragment</code> object,
|
||||
* all of its children are inserted, in the same order, before
|
||||
* <code>refChild</code>. If the <code>newChild</code> is already in the
|
||||
* tree, it is first removed.
|
||||
* @param newChild The node to insert.
|
||||
* @param refChild The reference node, i.e., the node before which the
|
||||
* new node must be inserted.
|
||||
* @return The node being inserted.
|
||||
* @exception DOMException
|
||||
* HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
|
||||
* allow children of the type of the <code>newChild</code> node, or if
|
||||
* the node to insert is one of this node's ancestors or this node
|
||||
* itself.
|
||||
* <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created
|
||||
* from a different document than the one that created this node.
|
||||
* <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly or
|
||||
* if the parent of the node being inserted is readonly.
|
||||
* <br>NOT_FOUND_ERR: Raised if <code>refChild</code> is not a child of
|
||||
* this node.
|
||||
*/
|
||||
NodeImpl* insertBefore(NodeImpl* newChild, NodeImpl* refChild) throw (DOMException);
|
||||
|
||||
/**
|
||||
* Removes the child node indicated by <code>oldChild</code> from the list
|
||||
* of children, and returns it.
|
||||
* @param oldChild The node being removed.
|
||||
* @return The node removed.
|
||||
* @exception DOMException
|
||||
* NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
|
||||
* <br>NOT_FOUND_ERR: Raised if <code>oldChild</code> is not a child of
|
||||
* this node.
|
||||
*/
|
||||
NodeImpl* removeChild(NodeImpl* oldChild) throw (DOMException);
|
||||
|
||||
/**
|
||||
* Adds the node <code>newChild</code> to the end of the list of children
|
||||
* of this node. If the <code>newChild</code> is already in the tree, it
|
||||
* is first removed.
|
||||
* @param newChild The node to add.If it is a
|
||||
* <code>DocumentFragment</code> object, the entire contents of the
|
||||
* document fragment are moved into the child list of this node
|
||||
* @return The node added.
|
||||
* @exception DOMException
|
||||
* HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
|
||||
* allow children of the type of the <code>newChild</code> node, or if
|
||||
* the node to append is one of this node's ancestors or this node
|
||||
* itself.
|
||||
* <br>WRONG_DOCUMENT_ERR: Raised if <code>newChild</code> was created
|
||||
* from a different document than the one that created this node.
|
||||
* <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly or
|
||||
* if the previous parent of the node being inserted is readonly.
|
||||
*/
|
||||
NodeImpl* appendChild(NodeImpl* newChild) throw (DOMException);
|
||||
|
||||
/**
|
||||
* Returns whether this node has any children.
|
||||
* @return <code>true</code> if this node has any children,
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
bool hasChildNodes() const;
|
||||
|
||||
virtual ~NodeImpl() {};
|
||||
|
||||
/**
|
||||
* Get the LayoutAttr of this node
|
||||
* @return the pointer to LayoutAttr
|
||||
*/
|
||||
virtual LayoutAttr* getLayoutAttr() const { return NULL;}
|
||||
|
||||
/**
|
||||
* Set the LayoutAttr of this node
|
||||
* @param attr the attributes to be set
|
||||
* @return void
|
||||
*/
|
||||
virtual void setLayoutAttr(LayoutAttr* attr) { return;}
|
||||
|
||||
/**
|
||||
* Set document context.
|
||||
* @param document The specify document context.
|
||||
*/
|
||||
void setDocument(const DocumentImpl* document);
|
||||
|
||||
/**
|
||||
* Get document context.
|
||||
* @return the current node's document context.
|
||||
*/
|
||||
const DocumentImpl* getDocument() const;
|
||||
};
|
||||
#endif /*__DOM_NODE_IMPL__*/
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __DOM_NODE_ITERATOR__
|
||||
#define __DOM_NODE_ITERATOR__
|
||||
class NodeImpl;
|
||||
/**
|
||||
* The Iterator is used to visit DOM_TREE.
|
||||
* <code>Attention</code>:The Iterator is not safe.
|
||||
* When the caller using the Iterator to access the tree,
|
||||
* the underlying data was modified, the next() or prev() may not return the right result.
|
||||
* means we have a <code>restriction</code>: the Iterator can only be used in the case that the tree structure will
|
||||
* not be modified before the end of iteration.
|
||||
*/
|
||||
class NodeIterator {
|
||||
private:
|
||||
NodeImpl* scopeNode;/** The specify the range of iterating */
|
||||
NodeImpl* endNode; /** The specify the end position of iterating */
|
||||
NodeImpl* curNode; /** The position of current node.*/
|
||||
|
||||
/**
|
||||
* Find the specify node's next order node.
|
||||
* @param node The specify node.
|
||||
* @return The next order node when success.
|
||||
* NULL when has an error.
|
||||
*/
|
||||
NodeImpl* findNextOrderNode(NodeImpl* node);
|
||||
|
||||
/**
|
||||
* Find the specify node's previous order node.
|
||||
* @param node The specify node.
|
||||
* @return The previous order node when success.
|
||||
* NULL when has an error.
|
||||
*/
|
||||
NodeImpl* findPreviousOrderNode(NodeImpl* node);
|
||||
public:
|
||||
/**
|
||||
* Construct for NodeIterator.
|
||||
* we must specify <code>start</code> value when we want iterate the DOM_TREE.
|
||||
* and we also can specify the <code>scope</code> if want restrict the range of iterator.
|
||||
* (eg: restrict the range of iterating at a subtree).otherwise it will iterate the whole DOM_TREE.
|
||||
* @param start The start position.
|
||||
* @param scope The scope of iterating.
|
||||
* @param end The end position of iterating.
|
||||
*/
|
||||
NodeIterator(NodeImpl* start, NodeImpl* scope = NULL, NodeImpl* end = NULL);
|
||||
|
||||
/**
|
||||
* Get next order node at current position in DOM_TREE.
|
||||
* @return NULL On there is not node can be get.
|
||||
* The pointer of node On can get next node.
|
||||
*/
|
||||
NodeImpl* next();
|
||||
|
||||
/**
|
||||
* Get next order node at current position in DOM_TREE.
|
||||
* @return NULL On there is not node can be get.
|
||||
* The pointer of node On can get previous node.
|
||||
*/
|
||||
NodeImpl* prev();
|
||||
};
|
||||
#endif /* __DOM_NODE_ITERATOR__ */
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __NODE_LIST_IMPL__
|
||||
#define __NODE_LIST_IMPL__
|
||||
|
||||
#include "NodeImpl.h"
|
||||
#include "Vector.h"
|
||||
class NodeListImpl {
|
||||
private:
|
||||
vector<const NodeImpl*> nodeList;
|
||||
public:
|
||||
/**
|
||||
* Add a special node into list.
|
||||
* @param newNode specify component.
|
||||
*/
|
||||
void append(const NodeImpl* newNode);
|
||||
|
||||
/**
|
||||
* Return The special position node pointer.
|
||||
* @param index The special position.
|
||||
* @return The node's pointer on success.
|
||||
* NULL when out of list's boundary.
|
||||
*/
|
||||
const NodeImpl* item(int index) const;
|
||||
|
||||
/**
|
||||
* Return the length of list.
|
||||
* @return the length of list.
|
||||
*/
|
||||
int getLength() const;
|
||||
|
||||
~NodeListImpl();
|
||||
};
|
||||
#endif /*__NODE_LIST_IMPL__ */
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __DOM_NODE_TYPE__
|
||||
#define __DOM_NODE_TYPE__
|
||||
enum NodeType {
|
||||
/**
|
||||
* The node is an <code>Element</code>.
|
||||
*/
|
||||
ELEMENT_NODE = 1,
|
||||
/**
|
||||
* The node is an <code>Attr</code>.
|
||||
*/
|
||||
ATTRIBUTE_NODE = 2,
|
||||
/**
|
||||
* The node is a <code>Text</code> node.
|
||||
*/
|
||||
TEXT_NODE = 3,
|
||||
/**
|
||||
* The node type is CDATASection.
|
||||
*/
|
||||
CDATA_SECTION_NODE = 4,
|
||||
/**
|
||||
* The node type is an EntityReference.
|
||||
*/
|
||||
ENTITY_REFERENCE_NODE = 5,
|
||||
/**
|
||||
* The node type is an <code>Entity</code>.
|
||||
*/
|
||||
ENTITY_NODE = 6,
|
||||
/**
|
||||
* The node type is a ProcessingInstruction.
|
||||
*/
|
||||
PROCESSING_INSTRUCTION_NODE = 7,
|
||||
/**
|
||||
* The node is a Comment
|
||||
*/
|
||||
COMMENT_NODE = 8,
|
||||
/**
|
||||
* The node is a Document.
|
||||
*/
|
||||
DOCUMENT_NODE = 9,
|
||||
/**
|
||||
* The node is a DocumentType.
|
||||
*/
|
||||
DOCUMENT_TYPE_NODE = 10,
|
||||
/**
|
||||
* The node is a DocumentFragment.
|
||||
*/
|
||||
DOCUMENT_FRAGMENT_NODE = 11,
|
||||
/**
|
||||
* The node is a Notation.
|
||||
*/
|
||||
NOTATION_NODE = 12,
|
||||
};
|
||||
#endif
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __DOM_TEXT_IMPL__
|
||||
#define __DOM_TEXT_IMPL__
|
||||
#include "CharacterDataImpl.h"
|
||||
class TextImpl:public CharacterDataImpl
|
||||
{
|
||||
private:
|
||||
const static DOMString nodeName;
|
||||
public:
|
||||
/** Text default constructor for TextImpl.*/
|
||||
TextImpl();
|
||||
|
||||
/**
|
||||
* Constructor for TextImpl
|
||||
* @param data The specify data to be set.
|
||||
*/
|
||||
TextImpl(const DOMString* data);
|
||||
|
||||
/** Override getNodeType method in NodeImpl.h */
|
||||
NodeType getNodeType() const;
|
||||
|
||||
/** Override getNodeName method in NodeImpl.h */
|
||||
const DOMString* getNodeName() const;
|
||||
};
|
||||
#endif /*__DOM_TEXT_IMPL__*/
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __VECTOR_H__
|
||||
#define __VECTOR_H__
|
||||
#include <uvector.h>
|
||||
using namespace ustl;
|
||||
#endif /*__VECTOR_H__*/
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __STACK_H__
|
||||
#define __STACK_H__
|
||||
#include <ustack.h>
|
||||
using namespace ustl;
|
||||
#endif /*__STACK_H__*/
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _DOMEXPATAGENT_
|
||||
#define _DOMEXPATAGENT_
|
||||
|
||||
#include <Drm2CommonTypes.h>
|
||||
#include <ofstream.h>
|
||||
#include <sostream.h>
|
||||
#include <ustring.h>
|
||||
#include <sistream.h>
|
||||
#include <util/domcore/NodeImpl.h>
|
||||
#include <util/domcore/DOMString.h>
|
||||
#include "ExpatWrapper.h"
|
||||
#include "XMLElementImpl.h"
|
||||
#include "XMLDocumentImpl.h"
|
||||
using namespace ustl;
|
||||
|
||||
class DomExpatAgent : public ExpatWrapper {
|
||||
public:
|
||||
/**
|
||||
* Constructor for DomExpatAgent.
|
||||
* @param xmlDocPtr XMLDocument pointer.
|
||||
*/
|
||||
DomExpatAgent(XMLDocumentImpl* xmlDocPtr);
|
||||
|
||||
/** Destructor for DomExpatAgent. */
|
||||
~DomExpatAgent();
|
||||
|
||||
/**
|
||||
* Generate XML DOM Document from XML source.
|
||||
* @param <code>xmlStream</code> the XML source stream.
|
||||
* @return ture or false to indicate whether generate successfully.
|
||||
*/
|
||||
bool generateDocumentFromXML(istringstream *xmlStream);
|
||||
|
||||
/**
|
||||
* Generate XML stream from XML DOM document.
|
||||
* @return xml stream.
|
||||
*/
|
||||
ostringstream* generateXMLFromDocument();
|
||||
|
||||
/**
|
||||
* deal with start element in Expat.
|
||||
*/
|
||||
virtual void startElement(const XML_Char *name,
|
||||
const XML_Char **atts);
|
||||
|
||||
/**
|
||||
* deal with end element for Expat.
|
||||
*/
|
||||
virtual void endElement(const XML_Char *name);
|
||||
|
||||
/**
|
||||
* deal with data handler for Expat.
|
||||
*/
|
||||
virtual void dataHandler(const XML_Char *s, int len);
|
||||
|
||||
PRIVATE:
|
||||
/**
|
||||
* Push a xml element with the specific tag name into stack.
|
||||
* @param name The name of tag.
|
||||
* @param atts The attributes of related tag.
|
||||
*/
|
||||
void pushTag(const DOMString *name, const XML_Char **atts);
|
||||
|
||||
/**
|
||||
* Append text into top element of stack.
|
||||
* @param text The data related to the present tag.
|
||||
*/
|
||||
void appendText(const DOMString *text);
|
||||
|
||||
/**
|
||||
* Pop the xml element with the specific tag name.
|
||||
* @param name The name of tag.
|
||||
*/
|
||||
void popTag(const DOMString *name);
|
||||
|
||||
/**
|
||||
* Traverse the XML DOM document starting from specific element.
|
||||
* @param root The specific element start to traverse.
|
||||
*/
|
||||
void traverse(ElementImpl *root);
|
||||
|
||||
PRIVATE:
|
||||
vector<NodeImpl*> mStack; /**< the stack to manage the tag. */
|
||||
XMLElementImpl* mTopElementPtr; /**< the top element of the stack. */
|
||||
XMLDocumentImpl* mXMLDocumentPtr; /**< XML DOM document pointer. */
|
||||
ostringstream mXMLostream; /**< xml output stream. */
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _XML_H_
|
||||
#define _XML_H_
|
||||
|
||||
#include <expat.h>
|
||||
#include <ustring.h>
|
||||
#include <Drm2CommonTypes.h>
|
||||
|
||||
using namespace ustl;
|
||||
|
||||
class ExpatWrapper {
|
||||
public:
|
||||
/**
|
||||
* Constructor for ExpatWrapper.
|
||||
*/
|
||||
ExpatWrapper();
|
||||
|
||||
/**
|
||||
* Destructor for ExpatWrapper.
|
||||
*/
|
||||
virtual ~ExpatWrapper();
|
||||
|
||||
/**
|
||||
* decode call expat to parse the xml.
|
||||
* @param buf The buffer to be parsed.
|
||||
* @param len The length of the buffer.
|
||||
* @param isFinal The flag to indicate whether the buffer
|
||||
* is a fragment or whole xml.
|
||||
*/
|
||||
int decode(const char* buf, int len, int isFinal);
|
||||
|
||||
/**
|
||||
* virtual funtion to deal with the start element in expat, need implement by child class.
|
||||
*/
|
||||
virtual void startElement(const XML_Char *name, const XML_Char **atts);
|
||||
|
||||
/**
|
||||
* virtual funtion to deal with the end element in expat, need implement by child class.
|
||||
*/
|
||||
virtual void endElement(const XML_Char *name);
|
||||
|
||||
/**
|
||||
* virtual funtion to deal with the data handler in expat, need implement by child class.
|
||||
*/
|
||||
virtual void dataHandler(const XML_Char *s, int len);
|
||||
|
||||
PRIVATE:
|
||||
/**
|
||||
* Callback for Expat startElement.
|
||||
*/
|
||||
static void startElementCallback(void *userData, const XML_Char *name, const XML_Char **atts);
|
||||
|
||||
/**
|
||||
* Callback for Expat endElement.
|
||||
*/
|
||||
static void endElementCallback(void *userData, const XML_Char *name);
|
||||
|
||||
/**
|
||||
* Callback for Expat dataHandler.
|
||||
*/
|
||||
static void dataHandlerCallback(void *userData, const XML_Char *s, int len);
|
||||
|
||||
PRIVATE:
|
||||
XML_Parser mParser; /**< The expat parser object. */
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _XMLDOCUMENTIMPL_H_
|
||||
#define _XMLDOCUMENTIMPL_H_
|
||||
|
||||
#include <Drm2CommonTypes.h>
|
||||
#include <util/domcore/DocumentImpl.h>
|
||||
|
||||
class XMLDocumentImpl : public DocumentImpl {
|
||||
public:
|
||||
/** Constructor for XMLDocumentImpl. */
|
||||
XMLDocumentImpl();
|
||||
|
||||
/** Destructor for XMLDocumentImpl. */
|
||||
~XMLDocumentImpl();
|
||||
|
||||
/**
|
||||
* Get the first child element of the document.
|
||||
* @return the first child <code>Element</code> of document.
|
||||
*/
|
||||
virtual ElementImpl* getDocumentElement() const;
|
||||
|
||||
/**
|
||||
* Create a XML element with the specific name.
|
||||
* @param tagName The specific tag name.
|
||||
* @return a new xml <code>Element</code>
|
||||
* @exception DOMException
|
||||
*/
|
||||
virtual ElementImpl* createElement(const DOMString* tagName) const throw (DOMException);
|
||||
|
||||
/**
|
||||
* Create a text node with the specific data.
|
||||
* @param data The specific data.
|
||||
* @return a new <code>Text</code> node.
|
||||
*/
|
||||
virtual TextImpl* createTextNode(const DOMString* data) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _XMLELEMENTIMPL_H_
|
||||
#define _XMLELEMENTIMPL_H_
|
||||
|
||||
#include <Drm2CommonTypes.h>
|
||||
#include <util/domcore/ElementImpl.h>
|
||||
#include <util/domcore/DOMString.h>
|
||||
#include <umap.h>
|
||||
#include <ustring.h>
|
||||
using namespace ustl;
|
||||
|
||||
typedef map<DOMString, DOMString> DOMStringMap;
|
||||
|
||||
class XMLElementImpl : public ElementImpl {
|
||||
public:
|
||||
/**
|
||||
* Constructor for XMLElementImpl.
|
||||
* @param tag The name of the tag.
|
||||
*/
|
||||
XMLElementImpl(const DOMString *tag);
|
||||
|
||||
/** Destructor for XMLElementImpl. */
|
||||
~XMLElementImpl();
|
||||
|
||||
/**
|
||||
* Get the attribute map of the XML element.
|
||||
* @return <code>DOMStringMap</code>
|
||||
*/
|
||||
const DOMStringMap* getAttributeMap() const;
|
||||
|
||||
/**
|
||||
* Get the tag name of the element.
|
||||
* return tag name.
|
||||
*/
|
||||
virtual const DOMString* getTagName() const;
|
||||
|
||||
/**
|
||||
* Set the attribute of the element.
|
||||
* @param name The key of the attribute.
|
||||
* @param value The value of the attribute.
|
||||
*/
|
||||
virtual void setAttribute(const DOMString* name, const DOMString* value) throw (DOMException);
|
||||
|
||||
/**
|
||||
* Remove the specific attribute.
|
||||
* @param name The key of the attribute.
|
||||
* @exception DOMException.
|
||||
*/
|
||||
virtual void removeAttribute(const DOMString* name) throw (DOMException);
|
||||
|
||||
/**
|
||||
* Get the specific attribute.
|
||||
* @param name The key of the attribute.
|
||||
* @return the value of the attribute.
|
||||
*/
|
||||
virtual const DOMString* getAttribute(const DOMString* name) const;
|
||||
|
||||
/**
|
||||
* Detect whether element has attributes or not.
|
||||
* @return true or false to indicate the result.
|
||||
*/
|
||||
virtual bool hasAttributes() const;
|
||||
|
||||
/**
|
||||
* Find the first child node in element by its tag name.
|
||||
* @param element the specific element to be found.
|
||||
* @param tag the specific tag name to be searched.
|
||||
* @return NULL if not found otherwise the child node.
|
||||
*/
|
||||
const NodeImpl* findSoloChildNode(const char* tag) const;
|
||||
|
||||
/**
|
||||
* Get the first text containted in first child of the element.
|
||||
* @param tag the specific tag name to be searched.
|
||||
* @return NULL if not found otherwise the text.
|
||||
*/
|
||||
const string* getSoloText(const char* tag) const;
|
||||
|
||||
/**
|
||||
* Get the first child xml element containted in the element.
|
||||
* @param tag the specific tag name to be searched.
|
||||
* @return NULL if not found otherwise the element.
|
||||
*/
|
||||
const XMLElementImpl* getSoloElement(const char* tag) const;
|
||||
|
||||
PRIVATE:
|
||||
DOMString mTagName; /**< The tag name. */
|
||||
DOMStringMap mAttributeMap; /** The map of attributes. */
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,206 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <dcf/DrmDcfCommon.h>
|
||||
|
||||
int64_t ntoh_int64(int64_t x)
|
||||
{
|
||||
return (((int64_t)(ntohl((int32_t)((x << 32) >> 32))) << 32) | (uint32_t)ntohl(((int32_t)(x >> 32))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Class: Box
|
||||
*/
|
||||
Box::Box(const uint8_t* box):mLargeSize(0),mUserType(NULL)
|
||||
{
|
||||
if(!box)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
const uint8_t* p = box;
|
||||
|
||||
/* Get the size value */
|
||||
mSize = ntohl(*(uint32_t *)p);
|
||||
p += sizeof(mSize);
|
||||
|
||||
/* Get the type value */
|
||||
mType = *((uint32_t *)p);
|
||||
p += sizeof(mType);
|
||||
|
||||
if (1 == mSize)
|
||||
{
|
||||
mLargeSize = ntoh_int64(*(uint64_t *)p);
|
||||
p += sizeof(mLargeSize);
|
||||
}
|
||||
|
||||
if (DCF_USER_TYPE == mType)
|
||||
{
|
||||
mUserType = new uint8_t[USER_TYPE_LEN];
|
||||
memcpy(mUserType, p, USER_TYPE_LEN);
|
||||
p += USER_TYPE_LEN;
|
||||
}
|
||||
|
||||
mBoxLength = p - box;
|
||||
}
|
||||
|
||||
Box::Box(const Box& other)
|
||||
{
|
||||
mSize = other.mSize;
|
||||
mType = other.mType;
|
||||
mLargeSize = other.mLargeSize;
|
||||
mUserType = NULL;
|
||||
|
||||
if(other.mUserType)
|
||||
{
|
||||
mUserType = new uint8_t[USER_TYPE_LEN];
|
||||
memcpy(mUserType,other.mUserType,USER_TYPE_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
Box& Box::operator=(const Box& other)
|
||||
{
|
||||
if(this == &other)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
if(mUserType)
|
||||
{
|
||||
delete []mUserType;
|
||||
mUserType = NULL;
|
||||
}
|
||||
|
||||
if(other.mUserType)
|
||||
{
|
||||
mUserType = new uint8_t[USER_TYPE_LEN];
|
||||
memcpy(mUserType, other.mUserType, USER_TYPE_LEN);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Box::~Box()
|
||||
{
|
||||
if(mUserType)
|
||||
{
|
||||
delete []mUserType;
|
||||
mUserType = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t Box::getSize(void) const
|
||||
{
|
||||
if(1 == mSize)
|
||||
{
|
||||
return mLargeSize;
|
||||
}
|
||||
|
||||
return mSize;
|
||||
}
|
||||
|
||||
uint32_t Box::getType(void) const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
const uint8_t* Box::getUsertype(void) const
|
||||
{
|
||||
return mUserType;
|
||||
}
|
||||
|
||||
uint32_t Box::getLen(void) const
|
||||
{
|
||||
return mBoxLength;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class: FullBox
|
||||
*/
|
||||
FullBox::FullBox(const uint8_t* fullBox) : Box(fullBox)
|
||||
{
|
||||
if(!fullBox)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
const uint8_t* p = fullBox;
|
||||
|
||||
p += Box::getLen();
|
||||
|
||||
mVersion = *p;
|
||||
p++;
|
||||
|
||||
memcpy(mFlag, p,FLAG_LEN);
|
||||
p += FLAG_LEN;
|
||||
|
||||
mFullBoxLength = p - fullBox;
|
||||
}
|
||||
|
||||
uint8_t FullBox::getVersion(void) const
|
||||
{
|
||||
return mVersion;
|
||||
}
|
||||
|
||||
const uint8_t* FullBox::getFlag(void) const
|
||||
{
|
||||
return mFlag;
|
||||
}
|
||||
|
||||
uint32_t FullBox::getLen(void) const
|
||||
{
|
||||
return mFullBoxLength;
|
||||
}
|
||||
|
||||
///// class TextualHeader implementation
|
||||
TextualHeader::TextualHeader(const string& inData)
|
||||
{
|
||||
string::size_type loc1 = inData.find(":", 0);
|
||||
|
||||
if (loc1 != string::npos)
|
||||
{
|
||||
name.assign(inData, 0, loc1);
|
||||
}
|
||||
|
||||
string::size_type loc2 = inData.find(";", loc1 + 1);
|
||||
|
||||
if (loc2 != string::npos)
|
||||
{
|
||||
value.assign(inData, loc1 + 1, loc2 - loc1 - 1);
|
||||
param.assign(inData, loc2 + 1, inData.length() - loc2 - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
value.assign(inData, loc1 + 1, inData.length() - loc1 - 1);
|
||||
}
|
||||
}
|
||||
|
||||
string TextualHeader::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
string TextualHeader::getValue() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
string TextualHeader::getParam() const
|
||||
{
|
||||
return param;
|
||||
}
|
||||
|
||||
@@ -1,294 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <dcf/DrmDcfContainer.h>
|
||||
|
||||
DcfContainer::DcfContainer(const uint8_t* data,istream& inRawData,uint64_t conOff)
|
||||
: FullBox(data),mConStream(inRawData)
|
||||
{
|
||||
if(!data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t* p = data;
|
||||
const uint8_t* flag = this->getFlag();
|
||||
|
||||
if(flag[0] & USER_DATA_FLAG)
|
||||
{
|
||||
mHasUserData = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mHasUserData = false;
|
||||
}
|
||||
|
||||
p += this->getLen();
|
||||
|
||||
FullBox fullBoxDiscrete(p);
|
||||
|
||||
p += fullBoxDiscrete.getLen();
|
||||
|
||||
mContentTypeLen = *p;
|
||||
p++;
|
||||
|
||||
mContentType.assign((const char*)p,0,mContentTypeLen);
|
||||
p += mContentTypeLen;
|
||||
|
||||
// parse common header
|
||||
FullBox fullBoxComm(p);
|
||||
p += fullBoxComm.getLen();
|
||||
|
||||
mEncryptionMethod = *p;
|
||||
p++;
|
||||
|
||||
mPaddingScheme = *p;
|
||||
p++;
|
||||
|
||||
mPlaintextLength = ntoh_int64(*((uint64_t *)p));
|
||||
p += sizeof(mPlaintextLength);
|
||||
|
||||
mContentIDLength = ntohs(*(uint16_t *)p);
|
||||
p += sizeof(mContentIDLength);
|
||||
|
||||
mRightsIssuerURLLength = ntohs(*(uint16_t *)p);
|
||||
p += sizeof(mRightsIssuerURLLength);
|
||||
|
||||
mTextualHeadersLength = ntohs(*(uint16_t *)p);
|
||||
p += sizeof(mTextualHeadersLength);
|
||||
|
||||
mContentID.assign((const char *)p,0,mContentIDLength);
|
||||
p += mContentIDLength;
|
||||
|
||||
mRightsIssuerURL.assign((const char *)p,0,mRightsIssuerURLLength);
|
||||
p += mRightsIssuerURLLength;
|
||||
|
||||
// parse textual header
|
||||
if (mTextualHeadersLength > 0)
|
||||
{
|
||||
if(false == parseTextualHeaders(p,mTextualHeadersLength))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
p += mTextualHeadersLength;
|
||||
}
|
||||
|
||||
////////////// parser group id
|
||||
|
||||
///parse content
|
||||
p = data + this->getLen() + fullBoxDiscrete.getSize();
|
||||
FullBox fullBoxContetn(p);
|
||||
p += fullBoxContetn.getLen();
|
||||
mDataLen = ntoh_int64(*((uint64_t *)p));
|
||||
p += sizeof(mDataLen);
|
||||
|
||||
mDecOffset = conOff + (p - data);
|
||||
p += mDataLen;
|
||||
|
||||
/////////////// parser user data
|
||||
}
|
||||
|
||||
DcfContainer::~DcfContainer()
|
||||
{
|
||||
uint32_t size = mTextualHeaders.size();
|
||||
|
||||
for(uint32_t i = 0; i < size; i++)
|
||||
{
|
||||
delete mTextualHeaders[i];
|
||||
}
|
||||
|
||||
mTextualHeaders.clear();
|
||||
mCustomHeader.clear();
|
||||
}
|
||||
|
||||
|
||||
string DcfContainer::getContentType(void) const
|
||||
{
|
||||
return mContentType;
|
||||
}
|
||||
|
||||
uint8_t DcfContainer::getEncryptionMethod(void) const
|
||||
{
|
||||
return mEncryptionMethod;
|
||||
}
|
||||
|
||||
uint8_t DcfContainer::getPaddingScheme(void) const
|
||||
{
|
||||
return mPaddingScheme;
|
||||
}
|
||||
|
||||
uint64_t DcfContainer::getPlaintextLength(void) const
|
||||
{
|
||||
return mPlaintextLength;
|
||||
}
|
||||
|
||||
uint16_t DcfContainer::getContentIDLength(void) const
|
||||
{
|
||||
return mContentIDLength;
|
||||
}
|
||||
|
||||
uint16_t DcfContainer::getRightsIssuerURLLength(void) const
|
||||
{
|
||||
return mRightsIssuerURLLength;
|
||||
}
|
||||
|
||||
uint16_t DcfContainer::getTextualHeadersLength(void) const
|
||||
{
|
||||
return mTextualHeadersLength;
|
||||
}
|
||||
|
||||
string DcfContainer::getContentID(void) const
|
||||
{
|
||||
return mContentID;
|
||||
}
|
||||
|
||||
string DcfContainer::getRightsIssuerURL(void) const
|
||||
{
|
||||
return mRightsIssuerURL;
|
||||
}
|
||||
|
||||
string DcfContainer::getPreviewMethod(void) const
|
||||
{
|
||||
return mSlientMethod;
|
||||
}
|
||||
|
||||
string DcfContainer::getContentLocation(void) const
|
||||
{
|
||||
return mContentLocation;
|
||||
}
|
||||
|
||||
string DcfContainer::getContentURL(void) const
|
||||
{
|
||||
return mContentURL;
|
||||
}
|
||||
|
||||
vector<string> DcfContainer::getCustomerHead(void) const
|
||||
{
|
||||
return mCustomHeader;
|
||||
}
|
||||
|
||||
istream& DcfContainer::getStream(void) const
|
||||
{
|
||||
return mConStream;
|
||||
}
|
||||
|
||||
DrmInStream DcfContainer::getPreviewElementData(void) const
|
||||
{
|
||||
// get data based on mPreviewElementURI
|
||||
//encryptedData = ;
|
||||
|
||||
DrmInStream inStream;
|
||||
return inStream;
|
||||
}
|
||||
|
||||
DrmInStream DcfContainer::getDecryptContent(uint8_t* decryptKey) const
|
||||
{
|
||||
DrmInStream inStream(this,decryptKey);
|
||||
return inStream;
|
||||
}
|
||||
|
||||
bool DcfContainer::parseTextualHeaders(const uint8_t* data, uint32_t len)
|
||||
{
|
||||
if(!data)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8_t* p = data;
|
||||
|
||||
while (len > (uint32_t)(p - data))
|
||||
{
|
||||
uint32_t l = strlen((const char*)p);
|
||||
|
||||
string str((const char*)p, l);
|
||||
TextualHeader* tmp = new TextualHeader(str);
|
||||
|
||||
if(!tmp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mTextualHeaders.push_back(tmp);
|
||||
|
||||
p += l + 1;
|
||||
}
|
||||
|
||||
uint32_t size = mTextualHeaders.size();
|
||||
uint32_t silentpos = 0;
|
||||
uint32_t previewpos = 0;
|
||||
|
||||
for( uint32_t i = 0; i < size; i++)
|
||||
{
|
||||
string tempStr = mTextualHeaders[i]->getName();
|
||||
|
||||
if(tempStr == "Silent")
|
||||
{
|
||||
silentpos = i;
|
||||
mSlientMethod = mTextualHeaders[i]->getValue();
|
||||
mSilentRightsURL = mTextualHeaders[i]->getParam();
|
||||
}
|
||||
else if(tempStr == "Preview")
|
||||
{
|
||||
previewpos = i;
|
||||
mPreviewMethod = mTextualHeaders[i]->getValue();
|
||||
|
||||
if(mPreviewMethod == "instant")
|
||||
{
|
||||
mPreviewElementURI = mTextualHeaders[i]->getParam();
|
||||
}
|
||||
else
|
||||
{
|
||||
mPreviewRightsURL = mTextualHeaders[i]->getParam();
|
||||
}
|
||||
}
|
||||
else if(tempStr == "ContentURL")
|
||||
{
|
||||
mContentURL = mTextualHeaders[i]->getValue();
|
||||
}
|
||||
else if(tempStr == "ContentVersion")
|
||||
{
|
||||
mContentVersion = mTextualHeaders[i]->getValue();
|
||||
}
|
||||
if(tempStr == "Content-Location")
|
||||
{
|
||||
mContentLocation = mTextualHeaders[i]->getValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
string str = mTextualHeaders[i]->getName();
|
||||
str += ":";
|
||||
str += mTextualHeaders[i]->getValue();
|
||||
mCustomHeader.push_back(str);
|
||||
}
|
||||
}
|
||||
|
||||
if(silentpos < previewpos)
|
||||
{
|
||||
mSilentFirst = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mSilentFirst = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <dcf/DrmIStream.h>
|
||||
|
||||
|
||||
DrmInStream::DrmInStream(const DcfContainer* container,uint8_t* Key)
|
||||
:mDcfCon(container),mDecryptPos(0)
|
||||
{
|
||||
memcpy(mAesKey,Key,AES_KEY_LEN);
|
||||
}
|
||||
|
||||
uint64_t DrmInStream::size() const
|
||||
{
|
||||
return mDcfCon->mPlaintextLength;
|
||||
}
|
||||
|
||||
uint64_t DrmInStream::read(uint8_t* data, uint64_t len)
|
||||
{
|
||||
if(!data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(mDecryptPos >= mDcfCon->mPlaintextLength)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t readLen = len;
|
||||
|
||||
// come to the end of decrypted data
|
||||
if(mDecryptPos + len > mDcfCon->mPlaintextLength)
|
||||
{
|
||||
readLen = mDcfCon->mPlaintextLength - mDecryptPos;
|
||||
}
|
||||
|
||||
uint64_t encLen = mDcfCon->mDataLen;
|
||||
uint8_t* encData = new uint8_t[encLen];
|
||||
|
||||
if(!encData)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
mDcfCon->mConStream.seek(mDcfCon->mDecOffset);
|
||||
mDcfCon->mConStream.read(encData,encLen);
|
||||
|
||||
uint8_t iv[AES_IV_LEN] = {0};
|
||||
|
||||
memcpy(iv,encData,AES_IV_LEN);
|
||||
encLen -= AES_IV_LEN;
|
||||
|
||||
if(AES_128_CBC != mDcfCon->mEncryptionMethod)
|
||||
{
|
||||
delete []encData;
|
||||
return 0;
|
||||
}
|
||||
|
||||
AesAgent drmAesDecrypt(AES_128_CBC,mAesKey);
|
||||
int32_t padLen = drmAesDecrypt.decContent( iv,
|
||||
encData + AES_IV_LEN,
|
||||
encLen,
|
||||
data);
|
||||
|
||||
delete []encData;
|
||||
|
||||
if(padLen >= 0)
|
||||
{
|
||||
return readLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <dcf/DrmRawContent.h>
|
||||
|
||||
|
||||
DrmRawContent::DrmRawContent(istream& inRawData)
|
||||
{
|
||||
uint32_t count = inRawData.stream_size();
|
||||
|
||||
if (count <= MAX_PIECE_LEN)
|
||||
{
|
||||
uint8_t* data = new uint8_t[count];
|
||||
|
||||
if(!data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
inRawData.read(data,count);
|
||||
|
||||
const uint8_t* dcf = data;
|
||||
|
||||
//parse DCF file header
|
||||
if(false == parseDcfHeader(dcf))
|
||||
{
|
||||
delete []data;
|
||||
return;
|
||||
}
|
||||
|
||||
dcf = data;
|
||||
dcf += FIX_HEADER_LEN;
|
||||
|
||||
if(dcf >= (data + count))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// parse container box
|
||||
FullBox conFullBox(dcf);
|
||||
|
||||
if(DCF_CONTAINER_BOX != conFullBox.getType())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//check whether it is multipart DCF or not
|
||||
do
|
||||
{
|
||||
uint64_t size = conFullBox.getSize();
|
||||
|
||||
mContainer.push_back(new DcfContainer(dcf,inRawData,dcf-data));
|
||||
|
||||
dcf += size;
|
||||
|
||||
// come to the end of raw content
|
||||
if(dcf >= (data + count))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
conFullBox = FullBox(dcf);
|
||||
}while(DCF_CONTAINER_BOX == conFullBox.getType());
|
||||
|
||||
// compute DCF hash using Sha1Agent
|
||||
Sha1Agent drmSha1Hash;
|
||||
drmSha1Hash.computeHash(data,dcf-data,mDcfHash);
|
||||
|
||||
//// parse mutable box
|
||||
|
||||
delete []data;
|
||||
}
|
||||
}
|
||||
|
||||
DrmRawContent::~DrmRawContent()
|
||||
{
|
||||
uint32_t size = mContainer.size();
|
||||
|
||||
for(uint32_t i = 0; i < size; i++)
|
||||
{
|
||||
delete mContainer[i];
|
||||
}
|
||||
|
||||
mContainer.clear();
|
||||
}
|
||||
|
||||
vector<DcfContainer*> DrmRawContent::getContents(void) const
|
||||
{
|
||||
return mContainer;
|
||||
}
|
||||
|
||||
uint32_t DrmRawContent::getDcfHashLen() const
|
||||
{
|
||||
return DCF_HASH_LEN;
|
||||
}
|
||||
|
||||
void DrmRawContent::getDcfHash(uint8_t* outDcfHash) const
|
||||
{
|
||||
if(outDcfHash)
|
||||
{
|
||||
memcpy(outDcfHash,mDcfHash,DCF_HASH_LEN);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool DrmRawContent::parseDcfHeader(const uint8_t* dcfHead)
|
||||
{
|
||||
if(!dcfHead)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(FIX_HEADER_LEN != ntohl(*(uint32_t *)dcfHead))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dcfHead += 4;
|
||||
uint32_t type = *(uint32_t *)dcfHead;
|
||||
|
||||
if(DCF_FILE_TYPE != type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dcfHead += 4;
|
||||
type = *(uint32_t *)dcfHead;
|
||||
|
||||
if(DCF_FILE_BRAND != type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dcfHead += 4;
|
||||
if(2 != ntohl(*(uint32_t *)dcfHead))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dcfHead += 4;
|
||||
type = *(uint32_t *)dcfHead;
|
||||
|
||||
if(DCF_FILE_BRAND != type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dcfHead += 4;
|
||||
return true;
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <drmmanager/DrmManager.h>
|
||||
#include <ustring.h>
|
||||
#include <ofstream.h>
|
||||
#include <sostream.h>
|
||||
#include <sistream.h>
|
||||
using namespace ustl;
|
||||
|
||||
/**see DrmManager.h */
|
||||
DrmManager::DrmManager(istream * inRawData)
|
||||
{
|
||||
mDcfStream = NULL;
|
||||
if (inRawData != NULL)
|
||||
{
|
||||
mDcfStream = inRawData;
|
||||
}
|
||||
}
|
||||
|
||||
/**see DrmManager.h */
|
||||
DrmManager::DrmManager(istream * inRawData, string mimeType)
|
||||
{
|
||||
mDcfStream = inRawData;
|
||||
}
|
||||
|
||||
/**see DrmManager.h */
|
||||
int16_t DrmManager::getListOfDcfObjects(vector<DcfContainer*> **outDcfList)
|
||||
{
|
||||
/** call dcf functions to parse the dcf file*/
|
||||
if (NULL == mDcfStream)
|
||||
{
|
||||
return ERR_DCFSTREAM_NOT_INITIALIZED;
|
||||
}
|
||||
if (NULL == outDcfList)
|
||||
{
|
||||
return ERR_DCFSTREAM_NOT_INITIALIZED;
|
||||
}
|
||||
*outDcfList=&mDcfs;
|
||||
return DRM_OK;
|
||||
}
|
||||
|
||||
/**see DrmManager.h */
|
||||
int16_t DrmManager::openDecryptedContent(DcfContainer *oneDcfObject,
|
||||
int16_t operationType,
|
||||
istream *outDecryptedData)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**see DrmManager.h */
|
||||
DrmManager::~DrmManager()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <rights/Asset.h>
|
||||
|
||||
/** see Asset.h */
|
||||
Asset::Asset()
|
||||
{}
|
||||
|
||||
/** see Asset.h */
|
||||
Asset::~Asset()
|
||||
{}
|
||||
|
||||
/** see Asset.h */
|
||||
bool Asset::hasParent()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/** see Asset.h */
|
||||
void Asset::setID(const string &id)
|
||||
{
|
||||
mAssetID = id;
|
||||
}
|
||||
|
||||
/** see Asset.h */
|
||||
const string& Asset::getID() const
|
||||
{
|
||||
return mAssetID;
|
||||
}
|
||||
|
||||
/** see Asset.h */
|
||||
void Asset::setContentID(const string &id)
|
||||
{
|
||||
mContentID = id;
|
||||
}
|
||||
|
||||
/** see Asset.h */
|
||||
const string& Asset::getContentID() const
|
||||
{
|
||||
return mContentID;
|
||||
}
|
||||
|
||||
/** see Asset.h */
|
||||
void Asset::setEncryptedKey(const string &key)
|
||||
{
|
||||
mEncryptedKey = key;
|
||||
}
|
||||
|
||||
/** see Asset.h */
|
||||
void Asset::setDCFDigest(const string &value)
|
||||
{
|
||||
mDigestValue = value;
|
||||
}
|
||||
|
||||
/** see Asset.h */
|
||||
const string& Asset::getDCFDigest() const
|
||||
{
|
||||
return mDigestValue;
|
||||
}
|
||||
|
||||
/** see Asset.h */
|
||||
void Asset::setKeyRetrievalMethod(const string &rm)
|
||||
{
|
||||
mRetrievalMethod = rm;
|
||||
}
|
||||
|
||||
/** see Asset.h */
|
||||
void Asset::setParentContentID(const string &id)
|
||||
{
|
||||
mParentContentID = id;
|
||||
}
|
||||
|
||||
/** see Asset.h */
|
||||
const string& Asset::getEncrytedKey() const
|
||||
{
|
||||
return mEncryptedKey;
|
||||
}
|
||||
|
||||
/** see Asset.h */
|
||||
const char* Asset::getCek() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** see Asset.h */
|
||||
void Asset::recoverCek()
|
||||
{
|
||||
//fix later.
|
||||
|
||||
}
|
||||
|
||||
/** see Asset.h */
|
||||
const string& Asset::getParentContentID() const
|
||||
{
|
||||
return mParentContentID;
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <rights/Constraint.h>
|
||||
|
||||
/** see Constraint.h */
|
||||
Constraint::Constraint()
|
||||
{
|
||||
mCount = INIT_VALUE;
|
||||
mTimedCount = INIT_VALUE;
|
||||
mTimer = INIT_VALUE;
|
||||
mStart = INIT_VALUE;
|
||||
mEnd = INIT_VALUE;
|
||||
mInterval = INIT_VALUE;
|
||||
mAccumulated = INIT_VALUE;
|
||||
mExport = NONE;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
Constraint::~Constraint()
|
||||
{}
|
||||
|
||||
/** see Constraint.h */
|
||||
bool Constraint::isUnConstraint() const
|
||||
{
|
||||
return (mCount == INIT_VALUE && mTimedCount == INIT_VALUE &&
|
||||
mTimer == INIT_VALUE && mStart == INIT_VALUE &&
|
||||
mEnd == INIT_VALUE && mInterval == INIT_VALUE &&
|
||||
mAccumulated == INIT_VALUE && mExport == NONE &&
|
||||
mSystemList.empty());
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
bool Constraint::isDateTimeConstraint() const
|
||||
{
|
||||
return !(mStart == INIT_VALUE && mEnd == INIT_VALUE);
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
bool Constraint::isIntervalConstraint() const
|
||||
{
|
||||
return !(mInterval == INIT_VALUE);
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
bool Constraint::isTimedCountConstraint() const
|
||||
{
|
||||
return !(mTimedCount == INIT_VALUE);
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
bool Constraint::isValid(long time) const
|
||||
{
|
||||
if (isUnConstraint())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isDateTimeConstraint())
|
||||
{
|
||||
if (time < mStart || time > mEnd)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mInterval == 0 || mCount == 0 ||
|
||||
mTimedCount == 0 || mAccumulated == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
void Constraint::setStartTime(long time)
|
||||
{
|
||||
mStart = time;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
long Constraint::getStartTime() const
|
||||
{
|
||||
return mStart;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
void Constraint::setEndTime(long time)
|
||||
{
|
||||
mEnd = time;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
long Constraint::getEndTime() const
|
||||
{
|
||||
return mEnd;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
void Constraint::setAccumulated(long time)
|
||||
{
|
||||
mAccumulated = time;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
long Constraint::getAccumulated() const
|
||||
{
|
||||
return mAccumulated;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
void Constraint::setCount(int count)
|
||||
{
|
||||
mCount = count;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
int Constraint::getCount() const
|
||||
{
|
||||
return mCount;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
void Constraint::setTimer(int timer)
|
||||
{
|
||||
mTimer = timer;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
int Constraint::getTimer() const
|
||||
{
|
||||
return mTimer;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
void Constraint::setTimedCount(int timedCount)
|
||||
{
|
||||
mTimedCount = timedCount;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
int Constraint::getTimedCount() const
|
||||
{
|
||||
return mTimedCount;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
void Constraint::setInterval(int interval)
|
||||
{
|
||||
mInterval = interval;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
int Constraint::getInterval() const
|
||||
{
|
||||
return mInterval;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
void Constraint::setExportMode(MODE mode)
|
||||
{
|
||||
mExport = mode;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
Constraint::MODE Constraint::getExportMode() const
|
||||
{
|
||||
return mExport;
|
||||
}
|
||||
|
||||
/** see Constraint.h */
|
||||
bool Constraint::consume()
|
||||
{
|
||||
if (isUnConstraint())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mCount > 0)
|
||||
{
|
||||
mCount--;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mAccumulated > 0)
|
||||
{
|
||||
mAccumulated--;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mTimedCount > 0)
|
||||
{
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <rights/OperationPermission.h>
|
||||
#include <rights/Constraint.h>
|
||||
|
||||
/** see OperationPermission.h */
|
||||
OperationPermission::OperationPermission() : mConstraint(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/** see OperationPermission.h */
|
||||
OperationPermission::OperationPermission(OPERATION type, Constraint *cst) : mType(type), mConstraint(cst)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/** see OperationPermission.h */
|
||||
OperationPermission::~OperationPermission()
|
||||
{
|
||||
delete mConstraint;
|
||||
}
|
||||
|
||||
/** see OperationPermission.h */
|
||||
void OperationPermission::setType(OPERATION type)
|
||||
{
|
||||
mType = type;
|
||||
}
|
||||
|
||||
/** see OperationPermission.h */
|
||||
OperationPermission::OPERATION OperationPermission::getType() const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
/** see OperationPermission.h */
|
||||
void OperationPermission::addConstraint(Constraint* constraint)
|
||||
{
|
||||
mConstraint = constraint;
|
||||
}
|
||||
|
||||
/** see OperationPermission.h */
|
||||
Constraint* OperationPermission::getConstraint() const
|
||||
{
|
||||
return mConstraint;
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <rights/Right.h>
|
||||
#include <rights/OperationPermission.h>
|
||||
#include <rights/Constraint.h>
|
||||
|
||||
/** see Right.h */
|
||||
Right::Right()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/** see Right.h */
|
||||
Right::~Right()
|
||||
{
|
||||
vector<OperationPermission*>::iterator it;
|
||||
|
||||
for (it = mOpList.begin(); it != mOpList.end(); it++)
|
||||
{
|
||||
delete(*it);
|
||||
}
|
||||
|
||||
mOpList.clear();
|
||||
}
|
||||
|
||||
/** see Right.h */
|
||||
void Right::addAssetID(const string& id)
|
||||
{
|
||||
mAssetNameList.push_back(id);
|
||||
}
|
||||
|
||||
/** see Right.h */
|
||||
void Right::addOperationPermission(OperationPermission* op)
|
||||
{
|
||||
mOpList.push_back(op);
|
||||
}
|
||||
|
||||
/** see Right.h */
|
||||
bool Right::checkPermission(OperationPermission::OPERATION type)
|
||||
{
|
||||
for (vector<OperationPermission*>::iterator it = mOpList.begin();
|
||||
it != mOpList.end(); it++)
|
||||
{
|
||||
if ((*it)->getType() == type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** see Right.h */
|
||||
Constraint* Right::getConstraint(OperationPermission::OPERATION type)
|
||||
{
|
||||
for (vector<OperationPermission*>::iterator it = mOpList.begin();
|
||||
it != mOpList.end(); it++)
|
||||
{
|
||||
if ((*it)->getType() == type)
|
||||
{
|
||||
return (*it)->getConstraint();
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,831 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <rights/Ro.h>
|
||||
#include <rights/Constraint.h>
|
||||
#include <rights/OperationPermission.h>
|
||||
#include <util/xml/DomExpatAgent.h>
|
||||
#include <util/domcore/DOMString.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <uassert.h>
|
||||
#include <time.h>
|
||||
#include <ofstream.h>
|
||||
using namespace ustl;
|
||||
|
||||
const char *STR_RO_RIGHTS = "o-ex:rights";
|
||||
const char *STR_RO_CONTEXT = "o-ex:context";
|
||||
const char *STR_RO_AGREEMENT = "o-ex:agreement";
|
||||
const char *STR_RO_ASSET = "o-ex:asset";
|
||||
const char *STR_RO_INHERIT = "o-ex:inherit";
|
||||
const char *STR_RO_DIGEST = "o-ex:digest";
|
||||
const char *STR_RO_KEYINFO = "ds:KeyInfo";
|
||||
const char *STR_RO_PERMISSION = "o-ex:permission";
|
||||
const char *STR_RO_ASSET_ID = "o-ex:id";
|
||||
const char *STR_RO_ASSET_IDREF = "o-ex:idref";
|
||||
const char *STR_RO_CONTEXT_ID = "o-dd:uid";
|
||||
const char *STR_RO_CONTEXT_VERSION = "o-dd:version";
|
||||
const char *STR_RO_DIGEST_VALUE = "ds:DigestValue";
|
||||
const char *STR_RO_CIPHER_VALUE = "xenc:CipherValue";
|
||||
const char *STR_RO_RETRIEVAL_METHOD = "ds:RetrievalMethod";
|
||||
const char *STR_RO_PLAY = "o-dd:play";
|
||||
const char *STR_RO_DISPLAY = "o-dd:display";
|
||||
const char *STR_RO_EXECUTE = "o-dd:execute";
|
||||
const char *STR_RO_PRINT = "o-dd:print";
|
||||
const char *STR_RO_EXPORT = "o-dd:export";
|
||||
const char *STR_RO_CONSTRAINT = "o-ex:constraint";
|
||||
const char *STR_RO_COUNT = "o-dd:count";
|
||||
const char *STR_RO_TIMEDCOUNT = "o-dd:timed-count";
|
||||
const char *STR_RO_TIMER = "oma-dd:timer";
|
||||
const char *STR_RO_INTERVAL = "o-dd:interval";
|
||||
const char *STR_RO_DATETIME = "o-dd:datetime";
|
||||
const char *STR_RO_START = "o-dd:start";
|
||||
const char *STR_RO_END = "o-dd:end";
|
||||
const char *STR_RO_ACCUMULATED = "o-dd:accumulated";
|
||||
const char *STR_RO_INDIVIDUAL = "o-dd:individual";
|
||||
const char *STR_RO_SYSTEM = "o-dd:system";
|
||||
|
||||
/** see Ro.h */
|
||||
Ro::Ro()
|
||||
{
|
||||
mDoc = new XMLDocumentImpl();
|
||||
mProperRight = NULL;
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
Ro::~Ro()
|
||||
{
|
||||
for (vector<Right*>::iterator itr = mRightList.begin(); itr != mRightList.end(); itr++)
|
||||
{
|
||||
delete(*itr);
|
||||
}
|
||||
|
||||
mRightList.clear();
|
||||
|
||||
for (vector<Asset*>::iterator ita = mAssetList.begin(); ita != mAssetList.end(); ita++)
|
||||
{
|
||||
delete(*ita);
|
||||
}
|
||||
|
||||
mAssetList.clear();
|
||||
|
||||
mProperRight = NULL;
|
||||
delete mDoc;
|
||||
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
void Ro::setRoID(string& id)
|
||||
{
|
||||
mRoID = id;
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
const string& Ro::getRoID() const
|
||||
{
|
||||
return mRoID;
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
void Ro::setRoVersion(string& version)
|
||||
{
|
||||
mRoVersion = version;
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
void Ro::addAsset(Asset* asset)
|
||||
{
|
||||
mAssetList.push_back(asset);
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
void Ro::addRight(Right* right)
|
||||
{
|
||||
mRightList.push_back(right);
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
bool Ro::save()
|
||||
{
|
||||
LOGI("==============Ro save.=================");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
Ro::ERRCODE Ro::parse(istringstream *roStream)
|
||||
{
|
||||
DomExpatAgent xmlAgent(mDoc);
|
||||
|
||||
if (NULL == roStream)
|
||||
{
|
||||
LOGI("NULL stream");
|
||||
return RO_NULL_STREAM;
|
||||
}
|
||||
|
||||
if (xmlAgent.generateDocumentFromXML(roStream) == false)
|
||||
{
|
||||
LOGI("generate xml doc error");
|
||||
return RO_ERR_BAD_XML;
|
||||
}
|
||||
|
||||
handleDocument(mDoc);
|
||||
|
||||
return RO_OK;
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
bool Ro::handleDocument(const XMLDocumentImpl* doc)
|
||||
{
|
||||
assert(doc != NULL);
|
||||
|
||||
NodeImpl* node = doc->getDocumentElement();
|
||||
|
||||
return handleRights(node);
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
bool Ro::handleRights(const NodeImpl *curNode)
|
||||
{
|
||||
assert(curNode != NULL);
|
||||
|
||||
NodeImpl *node = curNode->getFirstChild();
|
||||
|
||||
while (NULL != node)
|
||||
{
|
||||
const DOMString* name;
|
||||
|
||||
name = static_cast<const XMLElementImpl*>(node)->getTagName();
|
||||
|
||||
if (name->compare(STR_RO_CONTEXT) == 0)
|
||||
{
|
||||
LOGI("rights context");
|
||||
const DOMString *token = NULL;
|
||||
token = static_cast<const XMLElementImpl*>(node)->getSoloText(STR_RO_CONTEXT_ID);
|
||||
|
||||
if (token)
|
||||
{
|
||||
LOGI(*token);
|
||||
mRoID = *token;
|
||||
}
|
||||
|
||||
token = static_cast<const XMLElementImpl*>(node)->getSoloText(STR_RO_CONTEXT_VERSION);
|
||||
if (token)
|
||||
{
|
||||
LOGI(*token);
|
||||
mRoVersion = *token;
|
||||
}
|
||||
}
|
||||
|
||||
if (name->compare(STR_RO_AGREEMENT) == 0)
|
||||
{
|
||||
|
||||
LOGI("rights agreement");
|
||||
if (handleAgreement(node) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
node = node->getNextSibling();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
bool Ro::handleAgreement(const NodeImpl *curNode)
|
||||
{
|
||||
assert(curNode != NULL);
|
||||
|
||||
NodeImpl *node = curNode->getFirstChild();
|
||||
|
||||
while (NULL != node)
|
||||
{
|
||||
const DOMString* name;
|
||||
|
||||
name = static_cast<const XMLElementImpl*>(node)->getTagName();
|
||||
|
||||
if (name->compare(STR_RO_ASSET) == 0)
|
||||
{
|
||||
// do something about asset.
|
||||
LOGI("asset");
|
||||
|
||||
if (handleAsset(node) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (name->compare(STR_RO_PERMISSION) == 0)
|
||||
{
|
||||
// do something about permission.
|
||||
LOGI("permission");
|
||||
|
||||
if (handlePermission(node) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
node = node->getNextSibling();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
bool Ro::handleAsset(const NodeImpl *curNode)
|
||||
{
|
||||
assert(curNode != NULL);
|
||||
|
||||
Asset *asset = new Asset();
|
||||
|
||||
const XMLElementImpl *curElement = static_cast<const XMLElementImpl*>(curNode);
|
||||
|
||||
if (curElement->hasAttributes())
|
||||
{
|
||||
DOMString assetID(STR_RO_ASSET_ID);
|
||||
LOGI("asset id:");
|
||||
|
||||
const DOMString *id = curElement->getAttribute(&assetID);
|
||||
|
||||
if (id)
|
||||
{
|
||||
asset->setID(*id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NodeImpl* node = curNode->getFirstChild();
|
||||
|
||||
const DOMString *name = NULL;
|
||||
const string *token = NULL;
|
||||
|
||||
while (NULL != node)
|
||||
{
|
||||
curElement = static_cast<const XMLElementImpl*>(node);
|
||||
name = curElement->getTagName();
|
||||
|
||||
if (name->compare(STR_RO_CONTEXT) == 0 ||
|
||||
name->compare(STR_RO_INHERIT) == 0)
|
||||
{
|
||||
LOGI("asset context");
|
||||
|
||||
token = curElement->getSoloText(STR_RO_CONTEXT_ID);
|
||||
if (token)
|
||||
{
|
||||
LOGI(*token);
|
||||
|
||||
if (name->compare(STR_RO_CONTEXT) == 0)
|
||||
{
|
||||
asset->setContentID(*token);
|
||||
}
|
||||
else
|
||||
{
|
||||
//parent ID.
|
||||
asset->setParentContentID(*token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (name->compare(STR_RO_DIGEST) == 0)
|
||||
{
|
||||
LOGI("asset digest");
|
||||
//digest method is fixed value:
|
||||
//http://www.w3.org/2000/09/xmldisig#sha1
|
||||
token = curElement->getSoloText(STR_RO_DIGEST_VALUE);
|
||||
if (token)
|
||||
{
|
||||
LOGI(*token);
|
||||
asset->setDCFDigest(*token);
|
||||
}
|
||||
}
|
||||
|
||||
if (name->compare(STR_RO_KEYINFO) == 0)
|
||||
{
|
||||
LOGI("asset keyinfo");
|
||||
|
||||
token = curElement->getSoloText(STR_RO_CIPHER_VALUE);
|
||||
if (token)
|
||||
{
|
||||
LOGI(*token);
|
||||
asset->setEncryptedKey(*token);
|
||||
}
|
||||
|
||||
const XMLElementImpl *node = curElement->getSoloElement(STR_RO_RETRIEVAL_METHOD);
|
||||
|
||||
if (node)
|
||||
{
|
||||
if (node->hasAttributes())
|
||||
{
|
||||
DOMString uri("URI");
|
||||
token = node->getAttribute(&uri);
|
||||
if (token)
|
||||
{
|
||||
LOGI(*token);
|
||||
asset->setKeyRetrievalMethod(*token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node = node->getNextSibling();
|
||||
}
|
||||
|
||||
this->addAsset(asset);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
bool Ro::handlePermission(const NodeImpl *curNode)
|
||||
{
|
||||
assert(curNode != NULL);
|
||||
|
||||
Right *right = new Right();
|
||||
|
||||
const XMLElementImpl *curElement = static_cast<const XMLElementImpl*>(curNode);
|
||||
|
||||
NodeImpl* node = curNode->getFirstChild();
|
||||
|
||||
while (NULL != node)
|
||||
{
|
||||
const DOMString *name = NULL;
|
||||
NodeListImpl *nodeList = NULL;
|
||||
|
||||
const string *token = NULL;
|
||||
curElement = static_cast<const XMLElementImpl*>(node);
|
||||
name = curElement->getTagName();
|
||||
|
||||
if (name->compare(STR_RO_ASSET) == 0)
|
||||
{
|
||||
LOGI("permission asset");
|
||||
if (curElement->hasAttributes())
|
||||
{
|
||||
DOMString assetID(STR_RO_ASSET_IDREF);
|
||||
const DOMString *id = curElement->getAttribute(&assetID);
|
||||
if (id)
|
||||
{
|
||||
right->addAssetID(*id);
|
||||
LOGI(*id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OperationPermission::OPERATION type = OperationPermission::NONE;
|
||||
|
||||
if (name->compare(STR_RO_PLAY) == 0)
|
||||
{
|
||||
LOGI("permission play constraint");
|
||||
type = OperationPermission::PLAY;
|
||||
}
|
||||
|
||||
if (name->compare(STR_RO_DISPLAY) == 0)
|
||||
{
|
||||
LOGI("permission display costraint");
|
||||
type = OperationPermission::DISPLAY;
|
||||
}
|
||||
|
||||
if (name->compare(STR_RO_EXECUTE) == 0)
|
||||
{
|
||||
LOGI("permission execute constraint");
|
||||
type = OperationPermission::EXECUTE;
|
||||
}
|
||||
|
||||
if (name->compare(STR_RO_EXPORT) == 0)
|
||||
{
|
||||
LOGI("permission export constraint");
|
||||
type = OperationPermission::EXPORT;
|
||||
}
|
||||
|
||||
if (name->compare(STR_RO_PRINT) == 0)
|
||||
{
|
||||
LOGI("permission print constraint");
|
||||
type = OperationPermission::PRINT;
|
||||
}
|
||||
|
||||
Constraint *cst = NULL;
|
||||
|
||||
if (name->compare(STR_RO_CONSTRAINT) == 0)
|
||||
{
|
||||
LOGI("permission common constraint");
|
||||
type = OperationPermission::COMMON;
|
||||
}
|
||||
|
||||
cst = getConstraint(curElement);
|
||||
if (cst)
|
||||
{
|
||||
OperationPermission *op = new OperationPermission(type, cst);
|
||||
right->addOperationPermission(op);
|
||||
}
|
||||
|
||||
node = node->getNextSibling();
|
||||
}
|
||||
|
||||
this->addRight(right);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
long Ro::convertISO8601DateTimeToLong(const char* ts)
|
||||
{
|
||||
if (NULL == ts)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct tm time;
|
||||
memset(&time, 0, sizeof(struct tm));
|
||||
|
||||
strptime(ts, "%FT%T%z", &time);
|
||||
|
||||
//need timezone support: return mktime(&time) - timezone;
|
||||
//It seems android-sooner doesn't support timezone function.
|
||||
//line below is just for building, value would be wrong if no timezone minus.
|
||||
return mktime(&time);
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
long Ro::convertISO8601PeriodToLong(const char* ts)
|
||||
{
|
||||
if (NULL == ts)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int date, hour, min, sec;
|
||||
sscanf(ts, "P%dDT%dH%dM%dS", &date, &hour, &min, &sec);
|
||||
LOGI("%d %d %d %d", date, hour, min, sec);
|
||||
return (date*24*60*60 + hour*60*60 + min*60 + sec);
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
Constraint* Ro::getConstraint(const NodeImpl* curNode)
|
||||
{
|
||||
assert(curNode != NULL);
|
||||
|
||||
Constraint *constraint = new Constraint();
|
||||
|
||||
const XMLElementImpl *curElement = static_cast<const XMLElementImpl*>(curNode);
|
||||
|
||||
const string *name = NULL;
|
||||
const string *token = NULL;
|
||||
|
||||
if ((token = curElement->getSoloText(STR_RO_COUNT)))
|
||||
{
|
||||
LOGI(*token);
|
||||
constraint->setCount(atoi(token->c_str()));
|
||||
}
|
||||
|
||||
if ((token = curElement->getSoloText(STR_RO_START)))
|
||||
{
|
||||
LOGI(*token);
|
||||
//start Time
|
||||
constraint->setStartTime(convertISO8601DateTimeToLong(token->c_str()));
|
||||
}
|
||||
|
||||
if ((token = curElement->getSoloText(STR_RO_END)))
|
||||
{
|
||||
LOGI(*token);
|
||||
//end Time
|
||||
constraint->setEndTime(convertISO8601DateTimeToLong(token->c_str()));
|
||||
}
|
||||
|
||||
if ((token = curElement->getSoloText(STR_RO_INTERVAL)))
|
||||
{
|
||||
LOGI(*token);
|
||||
constraint->setInterval(atoi(token->c_str()));
|
||||
}
|
||||
|
||||
if ((token = curElement->getSoloText(STR_RO_ACCUMULATED)))
|
||||
{
|
||||
LOGI(*token);
|
||||
//Period
|
||||
constraint->setAccumulated(convertISO8601PeriodToLong(token->c_str()));
|
||||
}
|
||||
|
||||
if ((token = curElement->getSoloText(STR_RO_TIMEDCOUNT)))
|
||||
{
|
||||
LOGI(*token);
|
||||
constraint->setTimedCount(atoi(token->c_str()));
|
||||
|
||||
const XMLElementImpl *node = curElement->getSoloElement(STR_RO_TIMEDCOUNT);
|
||||
|
||||
if (node)
|
||||
{
|
||||
if (node->hasAttributes())
|
||||
{
|
||||
DOMString timer(STR_RO_TIMER);
|
||||
token = node->getAttribute(&timer);
|
||||
if (token)
|
||||
{
|
||||
LOGI(*token);
|
||||
constraint->setTimer(atoi(token->c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return constraint;
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
void Ro::loadRights(const string& contentID)
|
||||
{
|
||||
for (vector<Right*>::iterator it = this->mRightList.begin();
|
||||
it != this->mRightList.end(); it++)
|
||||
{
|
||||
if ((*it)->mAssetNameList.empty())
|
||||
{
|
||||
mContentRightList.push_back(*it);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (vector<Asset*>::iterator ita = this->mAssetList.begin();
|
||||
ita != this->mAssetList.end(); ita++)
|
||||
{
|
||||
for (vector<string>::iterator its = (*it)->mAssetNameList.begin();
|
||||
its != (*it)->mAssetNameList.end(); its++)
|
||||
{
|
||||
if ((*its).compare((*ita)->getID()) == 0)
|
||||
{
|
||||
if (contentID.compare((*ita)->getContentID()) == 0)
|
||||
{
|
||||
LOGI("find content right");
|
||||
mContentRightList.push_back(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
void Ro::freeRights()
|
||||
{
|
||||
mContentRightList.clear();
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
bool Ro::checkPermission(OperationPermission::OPERATION type,
|
||||
const string& contentID)
|
||||
{
|
||||
loadRights(contentID);
|
||||
|
||||
for (vector<Right*>::iterator it = mContentRightList.begin(); it != mContentRightList.end(); it++)
|
||||
{
|
||||
if ((*it)->checkPermission(type))
|
||||
{
|
||||
freeRights();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
freeRights();
|
||||
return false;
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
Ro::ERRCODE Ro::consume(OperationPermission::OPERATION type,
|
||||
const string& contentID)
|
||||
{
|
||||
loadRights(contentID);
|
||||
|
||||
//check in mRightList
|
||||
vector<Right*>::iterator it;
|
||||
vector<Right*> tmpList;
|
||||
vector<Right*> retList;
|
||||
Constraint *constraint = NULL;
|
||||
long ealiestEnd = -1;
|
||||
bool hasCommonConstraint = false;
|
||||
bool hasUnconstraint = false;
|
||||
bool hasDateTimeConstraint = false;
|
||||
bool hasTimedCountConstraint = false;
|
||||
bool hasIntervalConstraint = false;
|
||||
|
||||
|
||||
//apply the RO rule, if do not satisfy the constraint, .
|
||||
//proper right select process
|
||||
|
||||
for (it = mContentRightList.begin(); it != mContentRightList.end(); it++)
|
||||
{
|
||||
if ((*it)->checkPermission(type))
|
||||
{
|
||||
constraint = (*it)->getConstraint(OperationPermission::COMMON);
|
||||
if (constraint)
|
||||
{
|
||||
if (!constraint->isValid(time(NULL)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
hasCommonConstraint = true;
|
||||
tmpList.push_back(*it);
|
||||
}
|
||||
|
||||
constraint = (*it)->getConstraint(type);
|
||||
assert(constraint != NULL);
|
||||
|
||||
if (!constraint->isValid(time(NULL)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (constraint->isUnConstraint())
|
||||
{
|
||||
//use uncontrainted firstly.
|
||||
hasUnconstraint = true;
|
||||
tmpList.push_back(*it);
|
||||
break;
|
||||
}
|
||||
|
||||
if (constraint->isDateTimeConstraint())
|
||||
{
|
||||
//use datetime constraint in high priority.
|
||||
//if contain multipe constraints, use the earliest expire time.
|
||||
hasDateTimeConstraint = true;
|
||||
tmpList.push_back(*it);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (constraint->isTimedCountConstraint())
|
||||
{
|
||||
//illegal Operation when time counted
|
||||
if (type == OperationPermission::PRINT ||
|
||||
type == OperationPermission::EXPORT)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
hasTimedCountConstraint = true;
|
||||
tmpList.push_back(*it);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (constraint->isIntervalConstraint())
|
||||
{
|
||||
hasIntervalConstraint = true;
|
||||
tmpList.push_back(*it);
|
||||
continue;
|
||||
}
|
||||
|
||||
tmpList.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (it = tmpList.begin(); it != tmpList.end(); it++)
|
||||
{
|
||||
if (hasUnconstraint == true)
|
||||
{
|
||||
//delete other constraint
|
||||
constraint = (*it)->getConstraint(type);
|
||||
if (constraint)
|
||||
{
|
||||
if (constraint->isUnConstraint())
|
||||
{
|
||||
retList.push_back(*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hasDateTimeConstraint == true)
|
||||
{
|
||||
//delete other constraint
|
||||
constraint = (*it)->getConstraint(type);
|
||||
if (constraint)
|
||||
{
|
||||
if (constraint->isDateTimeConstraint())
|
||||
{
|
||||
long tt = constraint->getEndTime();
|
||||
|
||||
if (ealiestEnd == -1)
|
||||
{
|
||||
ealiestEnd = tt;
|
||||
retList.push_back(*it);
|
||||
}
|
||||
else if (ealiestEnd > tt)
|
||||
{
|
||||
ealiestEnd = tt;
|
||||
retList.pop_back();
|
||||
retList.push_back(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hasIntervalConstraint == true)
|
||||
{
|
||||
//delete other constraint
|
||||
constraint = (*it)->getConstraint(type);
|
||||
if (constraint)
|
||||
{
|
||||
if (constraint->isIntervalConstraint())
|
||||
{
|
||||
retList.push_back(*it);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hasTimedCountConstraint == true)
|
||||
{
|
||||
constraint = (*it)->getConstraint(type);
|
||||
if (constraint)
|
||||
{
|
||||
if (constraint->isTimedCountConstraint())
|
||||
{
|
||||
retList.push_back(*it);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
retList.push_back(*it);
|
||||
}
|
||||
|
||||
if (retList.size() == 0)
|
||||
{
|
||||
freeRights();
|
||||
return RO_BAD;
|
||||
}
|
||||
|
||||
LOGI("Proper right has %d", retList.size());
|
||||
|
||||
assert(retList.size() == 1);
|
||||
|
||||
mProperRight = retList[0];
|
||||
constraint = retList[0]->getConstraint(OperationPermission::COMMON);
|
||||
if (constraint)
|
||||
{
|
||||
if (constraint->consume() == false)
|
||||
{
|
||||
freeRights();
|
||||
return RO_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
constraint = retList[0]->getConstraint(type);
|
||||
if (constraint)
|
||||
{
|
||||
if (constraint->consume() == false)
|
||||
{
|
||||
freeRights();
|
||||
return RO_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
//update the constraint
|
||||
freeRights();
|
||||
return RO_OK;
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
string Ro::getContentCek(const string& contentID)
|
||||
{
|
||||
for (vector<Asset*>::iterator it = mAssetList.begin();
|
||||
it != mAssetList.end(); it++)
|
||||
{
|
||||
if (contentID.compare((*it)->getContentID()) == 0)
|
||||
{
|
||||
return (*it)->getCek();
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/** see Ro.h */
|
||||
string Ro::getContentHash(const string& contentID)
|
||||
{
|
||||
for (vector<Asset*>::iterator it = mAssetList.begin();
|
||||
it != mAssetList.end(); it++)
|
||||
{
|
||||
if (contentID.compare((*it)->getContentID()) == 0)
|
||||
{
|
||||
return (*it)->getDCFDigest();
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <rights/RoManager.h>
|
||||
#include <rights/Asset.h>
|
||||
|
||||
using namespace ustl;
|
||||
|
||||
RoManager* RoManager::msInstance = NULL;
|
||||
|
||||
/** see RoManager.h */
|
||||
RoManager* RoManager::Instance()
|
||||
{
|
||||
if (NULL == msInstance)
|
||||
{
|
||||
msInstance = new RoManager();
|
||||
}
|
||||
|
||||
return msInstance;
|
||||
}
|
||||
|
||||
/** see RoManager.h */
|
||||
RoManager::RoManager()
|
||||
{
|
||||
//load the ro list from local system.
|
||||
}
|
||||
|
||||
/** see RoManager.h */
|
||||
RoManager::~RoManager()
|
||||
{
|
||||
msInstance = NULL;
|
||||
|
||||
for (vector<Ro*>::iterator it = mRoList.begin();
|
||||
it != mRoList.end(); it++)
|
||||
{
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
mRoList.clear();
|
||||
}
|
||||
|
||||
/** see RoManager.h */
|
||||
Ro::ERRCODE RoManager::installRo(istringstream *roStream)
|
||||
{
|
||||
Ro *ro = new Ro();
|
||||
|
||||
Ro::ERRCODE ret = ro->parse(roStream);
|
||||
|
||||
if (Ro::RO_OK == ret)
|
||||
{
|
||||
ro->save();
|
||||
|
||||
mRoList.push_back(ro);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** see RoManager.h */
|
||||
Ro* RoManager::getRoByContentID(const string& contentID)
|
||||
{
|
||||
for (vector<Ro*>::iterator it = mRoList.begin();
|
||||
it != mRoList.end(); it++)
|
||||
{
|
||||
for (vector<Asset*>::iterator ita = (*it)->mAssetList.begin();
|
||||
ita != (*it)->mAssetList.end(); ita++)
|
||||
{
|
||||
if (contentID.compare((*ita)->getContentID()) == 0)
|
||||
{
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** see RoManager.h */
|
||||
Ro* RoManager::getRo(const string& roID)
|
||||
{
|
||||
for (vector<Ro*>::iterator it = mRoList.begin();
|
||||
it != mRoList.end(); it++)
|
||||
{
|
||||
if (roID.compare((*it)->getRoID()) == 0)
|
||||
{
|
||||
return (*it);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** see RoManager.h */
|
||||
vector<Ro*> RoManager::getAllRo()
|
||||
{
|
||||
return mRoList;
|
||||
}
|
||||
|
||||
/** see RoManager.h */
|
||||
bool RoManager::deleteRo(const string& roID)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/** see RoManager.h */
|
||||
bool RoManager::checkRoInCache(const string& roID)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/**/
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <roap/RoapMessageHandler.h>
|
||||
#include <util/xml/DomExpatAgent.h>
|
||||
#include <util/xml/XMLDocumentImpl.h>
|
||||
#include <util/domcore/NodeListImpl.h>
|
||||
#include <util/domcore/DOMString.h>
|
||||
#include <ofstream.h>
|
||||
using namespace ustl;
|
||||
|
||||
/**see RoapMessageHandler.h */
|
||||
RoapMessageHandler::RoapMessageHandler()
|
||||
{
|
||||
mDoc = NULL;
|
||||
}
|
||||
|
||||
/**see RoapMessageHandler.h */
|
||||
XMLDocumentImpl* RoapMessageHandler::createClientMsg(RoapMessageHandler::msgType type)
|
||||
{
|
||||
/* load template from files temporarily, FIX ME later */
|
||||
string msgTemplate;
|
||||
switch (type)
|
||||
{
|
||||
case RoapMessageHandler::DeviceHello:
|
||||
msgTemplate.append("deviceHello.xml");
|
||||
break;
|
||||
case RoapMessageHandler::RegistrationRequest:
|
||||
msgTemplate.append("deviceHello.xml");
|
||||
break;
|
||||
case RoapMessageHandler::RORequest:
|
||||
msgTemplate.append("deviceHello.xml");
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
ifstream xmlStream(msgTemplate.c_str());
|
||||
XMLDocumentImpl* xmlDoc = new XMLDocumentImpl();
|
||||
DomExpatAgent domExpatAgent1(xmlDoc);
|
||||
if (domExpatAgent1.generateDocumentFromXML(&xmlStream))
|
||||
{
|
||||
return xmlDoc;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete(xmlDoc);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,235 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <util/crypto/DrmCrypto.h>
|
||||
#include <ustring.h>
|
||||
|
||||
using namespace ustl;
|
||||
|
||||
void AesAgent::discardPaddingByte( unsigned char* decryptedBuf,unsigned long* decryptedBufLen)
|
||||
{
|
||||
if(!decryptedBuf)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
unsigned long tmpLen = *decryptedBufLen;
|
||||
|
||||
// Check whether the last several bytes are padding or not
|
||||
for ( i = 1; i < decryptedBuf[tmpLen - 1]; i++)
|
||||
{
|
||||
if (decryptedBuf[tmpLen - 1 - i] != decryptedBuf[tmpLen - 1])
|
||||
break;
|
||||
}
|
||||
|
||||
// They are padding bytes
|
||||
if (i == decryptedBuf[tmpLen - 1])
|
||||
{
|
||||
*decryptedBufLen = tmpLen - i;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t AesAgent::decContent( unsigned char* iv,
|
||||
const unsigned char* encData,
|
||||
unsigned long encLen,
|
||||
unsigned char* decData)
|
||||
{
|
||||
if(AES_128_CBC == mode)
|
||||
{
|
||||
AES_KEY key;
|
||||
AES_set_decrypt_key(AesKey,AES_KEY_BITS,&key);
|
||||
|
||||
uint8_t *tmpBuf = new uint8_t[encLen];
|
||||
|
||||
AES_cbc_encrypt( encData,
|
||||
tmpBuf,
|
||||
encLen,
|
||||
&key,
|
||||
iv,
|
||||
AES_DECRYPT);
|
||||
|
||||
unsigned long tempLen = encLen;
|
||||
discardPaddingByte(tmpBuf,&tempLen);
|
||||
|
||||
memcpy(decData, tmpBuf, tempLen);
|
||||
|
||||
delete []tmpBuf;
|
||||
return encLen - tempLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
return AES_DEC_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
void Sha1Agent::computeHash( const unsigned char* inData,
|
||||
unsigned long inLen,
|
||||
unsigned char* outHash) const
|
||||
{
|
||||
EVP_Digest(inData,inLen,outHash,NULL,EVP_sha1(),NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
void HmacSha1Agent::computeMac( const unsigned char* inData,
|
||||
unsigned long inLen,
|
||||
unsigned char* outData) const
|
||||
{
|
||||
HMAC(EVP_sha1(),macKey,keyLen,inData,inLen,outData,NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
bool RsaAgent::signature( const unsigned char* rawData,
|
||||
unsigned long rawLen,
|
||||
unsigned char* sigData,
|
||||
RsaAlg sigAlg)
|
||||
{
|
||||
switch(sigAlg)
|
||||
{
|
||||
case RSA_PSS:
|
||||
{
|
||||
unsigned char mHash[SHA_DIGEST_LENGTH];
|
||||
Sha1Agent sha1;
|
||||
sha1.computeHash(rawData,rawLen,mHash);
|
||||
|
||||
unsigned char EM[rsaSize];
|
||||
if( 0 == RSA_padding_add_PKCS1_PSS( &rsaKey,
|
||||
EM,
|
||||
mHash,
|
||||
EVP_sha1(),
|
||||
SHA_DIGEST_LENGTH))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(0 > RSA_private_encrypt( SHA_DIGEST_LENGTH,
|
||||
EM,
|
||||
sigData,
|
||||
&rsaKey,
|
||||
RSA_PKCS1_PADDING))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RSA_SHA1:
|
||||
{
|
||||
unsigned char mHash[SHA_DIGEST_LENGTH];
|
||||
Sha1Agent sha1;
|
||||
sha1.computeHash(rawData,rawLen,mHash);
|
||||
|
||||
if(0 != RSA_sign( NID_sha1WithRSA,
|
||||
mHash,
|
||||
SHA_DIGEST_LENGTH,
|
||||
sigData,
|
||||
&rsaSize,
|
||||
&rsaKey))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RsaAgent::sigVerify( unsigned char* sigData,
|
||||
unsigned long sigLen,
|
||||
const unsigned char* rawData,
|
||||
unsigned long rawLen,
|
||||
RsaAlg sigAlg)
|
||||
{
|
||||
if( sigAlg == RSA_PSS)
|
||||
{
|
||||
unsigned char decSigData[rsaSize];
|
||||
|
||||
if(0 > RSA_public_decrypt(sigLen,
|
||||
sigData,
|
||||
decSigData,
|
||||
&rsaKey,
|
||||
RSA_PKCS1_PADDING))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char mHash[SHA_DIGEST_LENGTH];
|
||||
Sha1Agent sha1;
|
||||
sha1.computeHash(rawData,rawLen,mHash);
|
||||
|
||||
if( 0 == RSA_verify_PKCS1_PSS( &rsaKey,
|
||||
mHash,
|
||||
EVP_sha1(),
|
||||
decSigData,
|
||||
-1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(sigAlg == RSA_SHA1)
|
||||
{
|
||||
unsigned char mHash[SHA_DIGEST_LENGTH];
|
||||
Sha1Agent sha1;
|
||||
sha1.computeHash(rawData,rawLen,mHash);
|
||||
|
||||
if(0 != RSA_verify( NID_sha1WithRSA,
|
||||
mHash,
|
||||
SHA_DIGEST_LENGTH,
|
||||
sigData,
|
||||
sigLen,
|
||||
&rsaKey))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int RsaAgent::decrypt( const unsigned char* encData,
|
||||
unsigned long encLen,
|
||||
unsigned char* decData)
|
||||
{
|
||||
return RSA_private_decrypt( encLen,
|
||||
encData,
|
||||
decData,
|
||||
&rsaKey,
|
||||
RSA_PKCS1_PADDING);
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <util/domcore/CharacterDataImpl.h>
|
||||
|
||||
/** see CharacterDataImpl.h */
|
||||
const DOMString* CharacterDataImpl::getData() const throw (DOMException)
|
||||
{
|
||||
return charData;
|
||||
}
|
||||
|
||||
/** see CharacterDataImpl.h */
|
||||
CharacterDataImpl::CharacterDataImpl():charData(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
/** see CharacterDataImpl.h*/
|
||||
CharacterDataImpl::CharacterDataImpl(const DOMString* data):charData(NULL)
|
||||
{
|
||||
if (data != NULL)
|
||||
charData = new DOMString(*data);
|
||||
}
|
||||
|
||||
/** see CharacterDataImpl.h */
|
||||
void CharacterDataImpl::setData(const DOMString* data) throw (DOMException)
|
||||
{
|
||||
|
||||
if (charData != NULL)
|
||||
delete charData;
|
||||
|
||||
if (data == NULL)
|
||||
charData = NULL;
|
||||
else
|
||||
charData = new DOMString(*data);
|
||||
}
|
||||
|
||||
/** see CharacterDataImpl.h */
|
||||
int CharacterDataImpl::getLength() const
|
||||
{
|
||||
return charData != NULL ? charData->length() : 0;
|
||||
}
|
||||
|
||||
/** see CharacterDataImpl.h */
|
||||
void CharacterDataImpl::appendData(const DOMString* arg) throw(DOMException)
|
||||
{
|
||||
if (arg != NULL) {
|
||||
if (charData != NULL)
|
||||
charData->append(*arg);
|
||||
else
|
||||
charData = new DOMString(*arg);
|
||||
}
|
||||
}
|
||||
|
||||
/** see CharacterDataImpl.h */
|
||||
const DOMString* CharacterDataImpl::getNodeValue() const throw(DOMException)
|
||||
{
|
||||
return getData();
|
||||
}
|
||||
|
||||
/** see CharacterDataImpl.h */
|
||||
void CharacterDataImpl::setNodeValue(DOMString* nodeValue) throw(DOMException)
|
||||
{
|
||||
setData(nodeValue);
|
||||
}
|
||||
|
||||
/** see CharacterDataImpl.h */
|
||||
CharacterDataImpl::~CharacterDataImpl()
|
||||
{
|
||||
delete charData;
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <util/domcore/DocumentImpl.h>
|
||||
|
||||
|
||||
const DOMString DocumentImpl::nodeName = "#DOCUMENT";
|
||||
|
||||
/** see DocumentImpl.h */
|
||||
DocumentImpl::DocumentImpl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/** see DocumentImpl.h */
|
||||
ElementImpl* DocumentImpl::getDocumentElement() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** see DocumentImpl.h */
|
||||
ElementImpl* DocumentImpl::createElement(const DOMString* tagName) const throw (DOMException)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** see DocumentImpl.h */
|
||||
TextImpl* DocumentImpl::createTextNode(const DOMString* data) const
|
||||
{
|
||||
TextImpl* text = new TextImpl(data);
|
||||
|
||||
if (text != NULL)
|
||||
text->setDocument(this);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
/** see DocumentImpl.h */
|
||||
NodeListImpl* DocumentImpl::getElementsByTagName(const DOMString* tagname) const
|
||||
{
|
||||
ElementImpl* element = getDocumentElement();
|
||||
NodeListImpl* list = NULL;
|
||||
|
||||
if (element != NULL)
|
||||
list = element->getElementsByTagName(tagname);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/** see DocumentImpl.h */
|
||||
const DOMString* DocumentImpl::getNodeName() const
|
||||
{
|
||||
return &nodeName;
|
||||
}
|
||||
|
||||
/** see DocumentImpl.h */
|
||||
NodeType DocumentImpl::getNodeType() const
|
||||
{
|
||||
return DOCUMENT_NODE;
|
||||
}
|
||||
|
||||
/** see DocumentImpl.h */
|
||||
DocumentImpl::~DocumentImpl()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <util/domcore/ElementImpl.h>
|
||||
|
||||
/** see ElementImpl.h */
|
||||
NodeType ElementImpl::getNodeType() const
|
||||
{
|
||||
return ELEMENT_NODE;
|
||||
}
|
||||
|
||||
/** see ElementImpl.h */
|
||||
const DOMString* ElementImpl::getNodeName() const
|
||||
{
|
||||
return getTagName();
|
||||
}
|
||||
|
||||
/** see ElementImpl.h */
|
||||
const DOMString* ElementImpl::getTagName() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** see ElementImpl.h */
|
||||
void ElementImpl::setAttribute(const DOMString* name, const DOMString* value) throw (DOMException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/** see ElementImpl.h */
|
||||
void ElementImpl::removeAttribute(const DOMString* name) throw (DOMException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/** see ElementImpl.h */
|
||||
const DOMString* ElementImpl::getAttribute(const DOMString* name) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** see ElementImpl.h */
|
||||
void ElementImpl::getElementsByTagName(const DOMString* name, NodeListImpl* nodeList) const
|
||||
{
|
||||
NodeImpl* node = getFirstChild();
|
||||
|
||||
if (node == NULL || name == NULL || nodeList == NULL)
|
||||
return;
|
||||
|
||||
do {
|
||||
|
||||
if (node->getNodeType() == ELEMENT_NODE) {
|
||||
ElementImpl* elementNode = static_cast<ElementImpl*>(node);
|
||||
if (*elementNode->getTagName() == *name)
|
||||
/* if current is element node and tag name is equal to <code>name</code>,put it into nodeList */
|
||||
nodeList->append(node);
|
||||
/*
|
||||
* visit DOM tree recursively,
|
||||
* get all Elements node whose tage name is equal to name.
|
||||
*/
|
||||
elementNode->getElementsByTagName(name, nodeList);
|
||||
}
|
||||
|
||||
/* set current node's next sibling node as current node.*/
|
||||
node = node->getNextSibling();
|
||||
} while(node != NULL);
|
||||
}
|
||||
|
||||
/** see ElementImpl.h */
|
||||
NodeListImpl* ElementImpl::getElementsByTagName(const DOMString* name) const
|
||||
{
|
||||
NodeListImpl* nodeList = new NodeListImpl();
|
||||
|
||||
if (nodeList == NULL || name == NULL)
|
||||
return NULL;
|
||||
|
||||
getElementsByTagName(name,nodeList);
|
||||
|
||||
return nodeList;
|
||||
}
|
||||
|
||||
/** see ElementImpl.h */
|
||||
bool ElementImpl::hasAttributes() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <util/domcore/NodeImpl.h>
|
||||
#include <util/domcore/DocumentImpl.h>
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
void NodeImpl::setParent(NodeImpl* parentNode)
|
||||
{
|
||||
this->parent = parentNode;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
void NodeImpl::setNextSibling(NodeImpl* siblingNode)
|
||||
{
|
||||
this->nextSibling = siblingNode;
|
||||
}
|
||||
/** see NodeImpl.h. */
|
||||
void NodeImpl::setPreviousSibling(NodeImpl* siblingNode)
|
||||
{
|
||||
this->previousSibling = siblingNode;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
void NodeImpl::setFirstChild(NodeImpl* childNode)
|
||||
{
|
||||
this->firstChild = childNode;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
void NodeImpl::setLastChild(NodeImpl* childNode)
|
||||
{
|
||||
this->lastChild = childNode;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
NodeImpl* NodeImpl::getParentNode() const
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
NodeImpl* NodeImpl::getFirstChild() const
|
||||
{
|
||||
return firstChild;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
NodeImpl* NodeImpl::getLastChild() const
|
||||
{
|
||||
return lastChild;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
NodeImpl* NodeImpl::getPreviousSibling() const
|
||||
{
|
||||
return previousSibling;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
NodeImpl* NodeImpl::getNextSibling() const
|
||||
{
|
||||
return nextSibling;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
NodeImpl* NodeImpl::insertBefore(NodeImpl* newChild, NodeImpl* refChild) throw (DOMException)
|
||||
{
|
||||
if (newChild == NULL)
|
||||
#if PLATFORM_ANDROID
|
||||
return NULL;
|
||||
#else
|
||||
throw DOMException(DOMException::WRONG_DOCUMENT_ERR);
|
||||
#endif
|
||||
if (refChild == NULL || refChild->getParentNode() != this)
|
||||
#if PLATFORM_ANDROID
|
||||
return NULL;
|
||||
#else
|
||||
throw DOMException(DOMException::NOT_FOUND_ERR);
|
||||
#endif
|
||||
|
||||
NodeImpl* parentNode = newChild->getParentNode();
|
||||
|
||||
if (parentNode != NULL)
|
||||
parentNode->removeChild(newChild);
|
||||
|
||||
NodeImpl* prevSiblingNode = refChild->getPreviousSibling();
|
||||
|
||||
if (prevSiblingNode != NULL)
|
||||
prevSiblingNode->appendNextSibling(newChild);
|
||||
else
|
||||
setFirstChild(newChild);
|
||||
|
||||
newChild->appendNextSibling(refChild);
|
||||
newChild->setParent(this);
|
||||
|
||||
return newChild;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
NodeImpl* NodeImpl::removeChild(NodeImpl* oldChild) throw (DOMException)
|
||||
{
|
||||
|
||||
if (oldChild == NULL || oldChild->getParentNode() != this )
|
||||
#if PLATFORM_ANDROID
|
||||
return NULL;
|
||||
#else
|
||||
throw DOMException(DOMException::NOT_FOUND_ERR);
|
||||
#endif
|
||||
|
||||
NodeImpl* parentNode = oldChild->getParentNode();
|
||||
NodeImpl* nextSiblingNode = oldChild->getNextSibling();
|
||||
NodeImpl* prevSiblingNode = oldChild->getPreviousSibling();
|
||||
|
||||
if (prevSiblingNode == NULL && nextSiblingNode != NULL) {
|
||||
/*
|
||||
* children's previous sibling node == NULL and next sibling node !=
|
||||
* NULL, means the children node is the first node of its parent.
|
||||
* so set the children's next sibling node as the first node of its parent.
|
||||
*/
|
||||
parentNode->setFirstChild(nextSiblingNode);
|
||||
nextSiblingNode->setPreviousSibling(NULL);
|
||||
|
||||
} else if (prevSiblingNode != NULL && nextSiblingNode == NULL) {
|
||||
/*
|
||||
* children's previous sibling node != NULL and next sibling node ==
|
||||
* NULL, means the child node is the last node of parent.so set the
|
||||
* last node of children's parent as children's previous sibling node.
|
||||
*/
|
||||
prevSiblingNode->setNextSibling(NULL);
|
||||
parentNode->setLastChild(prevSiblingNode);
|
||||
|
||||
} else if (prevSiblingNode != NULL && nextSiblingNode != NULL) {
|
||||
/*
|
||||
* children's previous sibling node != NULL and next sibling node !=
|
||||
* NULL,means the node is neither first child nor last children of its parent.
|
||||
*/
|
||||
prevSiblingNode->appendNextSibling(nextSiblingNode);
|
||||
|
||||
} else if (prevSiblingNode == NULL && nextSiblingNode == NULL) {
|
||||
/*
|
||||
* this means it's only one children node of its parent.
|
||||
* so adjust the first child and last child to NULL when remove the children node.
|
||||
*/
|
||||
this->setFirstChild(NULL);
|
||||
this->setLastChild(NULL);
|
||||
}
|
||||
|
||||
oldChild->setParent(NULL);
|
||||
oldChild->setNextSibling(NULL);
|
||||
oldChild->setPreviousSibling(NULL);
|
||||
|
||||
return oldChild;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
void NodeImpl::appendNextSibling(NodeImpl* node)
|
||||
{
|
||||
if (node == NULL)
|
||||
return;
|
||||
|
||||
setNextSibling(node);
|
||||
node->setPreviousSibling(this);
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
NodeImpl* NodeImpl::appendChild(NodeImpl* newChild) throw (DOMException)
|
||||
{
|
||||
if (newChild == NULL)
|
||||
#if PLATFORM_ANDROID
|
||||
return NULL;
|
||||
#else
|
||||
throw DOMException(DOMException::WRONG_DOCUMENT_ERR);
|
||||
#endif
|
||||
/* If newChild have parent,remove it from its parent at first.*/
|
||||
NodeImpl* parent = newChild->getParentNode();
|
||||
if (parent != NULL)
|
||||
parent->removeChild(newChild);
|
||||
|
||||
if (getFirstChild() == NULL && getLastChild() == NULL) {
|
||||
/* There are not any nodes in current node.*/
|
||||
setFirstChild(newChild);
|
||||
} else if (getLastChild() != NULL) {
|
||||
getLastChild()->appendNextSibling(newChild);
|
||||
}
|
||||
|
||||
newChild->setParent(this);
|
||||
setLastChild(newChild);
|
||||
|
||||
|
||||
return newChild;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
bool NodeImpl::hasChildNodes() const
|
||||
{
|
||||
return getFirstChild() != NULL;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
const DOMString* NodeImpl::getNodeValue() const throw (DOMException)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
void NodeImpl::setNodeValue(DOMString* nodeValue) throw (DOMException)
|
||||
{
|
||||
}
|
||||
|
||||
/** see NodeImpl.h. */
|
||||
bool NodeImpl::hasAttributes() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h */
|
||||
const DocumentImpl* NodeImpl::getDocument() const
|
||||
{
|
||||
return document;
|
||||
}
|
||||
|
||||
/** see NodeImpl.h */
|
||||
void NodeImpl::setDocument(const DocumentImpl* document)
|
||||
{
|
||||
this->document = document;
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <util/domcore/NodeImpl.h>
|
||||
#include <util/domcore/NodeIterator.h>
|
||||
|
||||
/** see NodeIterator.h */
|
||||
NodeIterator::NodeIterator(NodeImpl* start,NodeImpl* scope,NodeImpl* end): scopeNode(scope),endNode(end),curNode(start)
|
||||
{
|
||||
}
|
||||
|
||||
/** see NodeIterator.h */
|
||||
NodeImpl* NodeIterator::findNextOrderNode(NodeImpl* node)
|
||||
{
|
||||
if (node == endNode)
|
||||
return NULL;
|
||||
|
||||
if (node != NULL) {
|
||||
if (node->hasChildNodes() == true) {
|
||||
node = node->getFirstChild();
|
||||
}else if (node == scopeNode && node->hasChildNodes() == false) {
|
||||
node = NULL;
|
||||
} else if (node->getNextSibling() != NULL) {
|
||||
node = node->getNextSibling();
|
||||
} else {
|
||||
while (node != scopeNode && node != NULL && node->getNextSibling() == NULL) {
|
||||
node = node->getParentNode();
|
||||
}
|
||||
if (node == scopeNode)
|
||||
node = NULL;
|
||||
if (node != NULL)
|
||||
node = node->getNextSibling();
|
||||
}
|
||||
}
|
||||
if (node == endNode || node == scopeNode)
|
||||
node = NULL;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/** see NodeIterator.h */
|
||||
NodeImpl* NodeIterator::next()
|
||||
{
|
||||
NodeImpl* node = NULL;
|
||||
|
||||
node = findNextOrderNode(curNode);
|
||||
|
||||
if (node != NULL)
|
||||
curNode = node;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/** see NodeIterator.h */
|
||||
NodeImpl* NodeIterator::prev()
|
||||
{
|
||||
NodeImpl* node;
|
||||
|
||||
node = findPreviousOrderNode(curNode);
|
||||
|
||||
if (node != NULL)
|
||||
curNode = node;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/** see NodeIterator.h */
|
||||
NodeImpl* NodeIterator::findPreviousOrderNode(NodeImpl* node)
|
||||
{
|
||||
if (node == NULL || node == endNode)
|
||||
return NULL;
|
||||
|
||||
if (node->getPreviousSibling() != NULL) {
|
||||
node = node->getPreviousSibling();
|
||||
while(node != NULL && node->hasChildNodes() == true)
|
||||
node = node->getLastChild();
|
||||
} else {
|
||||
if (node == scopeNode)
|
||||
node = NULL;
|
||||
else
|
||||
node = node->getParentNode();
|
||||
}
|
||||
|
||||
if (node == scopeNode || node == endNode)
|
||||
return NULL;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <util/domcore/NodeListImpl.h>
|
||||
|
||||
/** see NodeListImpl.h*/
|
||||
void NodeListImpl::append(const NodeImpl* newNode)
|
||||
{
|
||||
if (newNode == NULL)
|
||||
return;
|
||||
|
||||
nodeList.push_back(newNode);
|
||||
}
|
||||
|
||||
/** see NodeListImpl.h*/
|
||||
const NodeImpl* NodeListImpl::item(int index) const
|
||||
{
|
||||
int size = nodeList.size();
|
||||
|
||||
if (size == 0 || index > size - 1 || index < 0)
|
||||
return NULL;
|
||||
|
||||
return nodeList.at(index);
|
||||
}
|
||||
|
||||
/** see NodeListImpl.h*/
|
||||
int NodeListImpl::getLength() const
|
||||
{
|
||||
return nodeList.size();
|
||||
}
|
||||
|
||||
/** see NodeListImpl.h*/
|
||||
NodeListImpl::~NodeListImpl()
|
||||
{
|
||||
nodeList.clear();
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* 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 <util/domcore/TextImpl.h>
|
||||
|
||||
const DOMString TextImpl::nodeName = "#TEXT";
|
||||
|
||||
/** see TextImpl.h */
|
||||
TextImpl::TextImpl()
|
||||
{
|
||||
}
|
||||
|
||||
/** see TextImpl.h */
|
||||
TextImpl::TextImpl(const DOMString* data):CharacterDataImpl(data)
|
||||
{
|
||||
}
|
||||
|
||||
/** see TextImpl.h */
|
||||
NodeType TextImpl::getNodeType() const
|
||||
{
|
||||
return TEXT_NODE;
|
||||
}
|
||||
|
||||
/** see TextImpl.h */
|
||||
const DOMString* TextImpl::getNodeName() const
|
||||
{
|
||||
return &nodeName;
|
||||
}
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2006 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// bktrace.cc
|
||||
//
|
||||
|
||||
#include "bktrace.h"
|
||||
#include "sostream.h"
|
||||
#include "mistream.h"
|
||||
#include "uassert.h"
|
||||
#if linux && __GNUC__ && !defined(HAVE_ANDROID_OS)
|
||||
#include <execinfo.h>
|
||||
#else
|
||||
static inline int backtrace (void**, int) { return (0); }
|
||||
static inline char** backtrace_symbols (void* const*, int) { return (NULL); }
|
||||
#endif
|
||||
#if __GNUC__ >= 3 && !PLATFORM_ANDROID
|
||||
#include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// Default constructor. The backtrace is obtained here.
|
||||
CBacktrace::CBacktrace (void)
|
||||
: m_Symbols (NULL),
|
||||
m_nFrames (0),
|
||||
m_SymbolsSize (0)
|
||||
{
|
||||
#if !PLATFORM_ANDROID
|
||||
try {
|
||||
#endif
|
||||
m_nFrames = backtrace (VectorBlock (m_Addresses));
|
||||
GetSymbols();
|
||||
#if !PLATFORM_ANDROID
|
||||
} catch (...) {}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Copy constructor.
|
||||
CBacktrace::CBacktrace (const CBacktrace& v)
|
||||
: m_Symbols (NULL),
|
||||
m_nFrames (0),
|
||||
m_SymbolsSize (0)
|
||||
{
|
||||
operator= (v);
|
||||
}
|
||||
|
||||
/// Copy operator.
|
||||
const CBacktrace& CBacktrace::operator= (const CBacktrace& v)
|
||||
{
|
||||
memcpy (m_Addresses, v.m_Addresses, sizeof(m_Addresses));
|
||||
m_Symbols = strdup (v.m_Symbols);
|
||||
m_nFrames = v.m_nFrames;
|
||||
m_SymbolsSize = v.m_SymbolsSize;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
/// Converts a string returned by backtrace_symbols into readable form.
|
||||
static size_t ExtractAbiName (const char* isym, char* nmbuf)
|
||||
{
|
||||
// Prepare the demangled name, if possible
|
||||
size_t nmSize = 0;
|
||||
if (isym) {
|
||||
// Copy out the name; the strings are: "file(function+0x42) [0xAddress]"
|
||||
const char* mnStart = strchr (isym, '(');
|
||||
if (++mnStart == (const char*)(1))
|
||||
mnStart = isym;
|
||||
const char* mnEnd = strchr (isym, '+');
|
||||
const char* isymEnd = isym + strlen (isym);
|
||||
if (!mnEnd)
|
||||
mnEnd = isymEnd;
|
||||
nmSize = min (size_t (distance (mnStart, mnEnd)), 256U);
|
||||
memcpy (nmbuf, mnStart, nmSize);
|
||||
}
|
||||
nmbuf[nmSize] = 0;
|
||||
// Demangle
|
||||
demangle_type_name (nmbuf, 256U, &nmSize);
|
||||
return (nmSize);
|
||||
}
|
||||
|
||||
/// Tries to get symbol information for the addresses.
|
||||
void CBacktrace::GetSymbols (void)
|
||||
{
|
||||
auto_ptr<char*> symbols (backtrace_symbols (m_Addresses, m_nFrames));
|
||||
if (!symbols.get())
|
||||
return;
|
||||
char nmbuf [256];
|
||||
size_t symSize = 1;
|
||||
for (uoff_t i = 0; i < m_nFrames; ++ i)
|
||||
symSize += ExtractAbiName (symbols.get()[i], nmbuf) + 1;
|
||||
if (!(m_Symbols = (char*) calloc (symSize, 1)))
|
||||
return;
|
||||
for (uoff_t i = 0; m_SymbolsSize < symSize - 1; ++ i) {
|
||||
size_t sz = ExtractAbiName (symbols.get()[i], nmbuf);
|
||||
memcpy (m_Symbols + m_SymbolsSize, nmbuf, sz);
|
||||
m_SymbolsSize += sz + 1;
|
||||
m_Symbols [m_SymbolsSize - 1] = '\n';
|
||||
}
|
||||
}
|
||||
|
||||
/// Default destructor.
|
||||
CBacktrace::~CBacktrace (void)
|
||||
{
|
||||
free_nullok (m_Symbols);
|
||||
}
|
||||
|
||||
#if SIZE_OF_LONG == 8
|
||||
#define ADDRESS_FMT "%16p "
|
||||
#else
|
||||
#define ADDRESS_FMT "%8p "
|
||||
#endif
|
||||
|
||||
/// Prints the backtrace to \p os.
|
||||
void CBacktrace::text_write (ostringstream& os) const
|
||||
{
|
||||
const char *ss = m_Symbols, *se;
|
||||
for (uoff_t i = 0; i < m_nFrames; ++ i) {
|
||||
os.format (ADDRESS_FMT, m_Addresses[i]);
|
||||
se = strchr (ss, '\n') + 1;
|
||||
os.write (ss, distance (ss, se));
|
||||
ss = se;
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads the object from stream \p is.
|
||||
void CBacktrace::read (istream& is)
|
||||
{
|
||||
assert (is.aligned (alignof (m_Addresses[0])) && "Backtrace object contains pointers and must be void* aligned");
|
||||
is >> m_nFrames >> m_SymbolsSize;
|
||||
free_nullok (m_Symbols);
|
||||
m_Symbols = (char*) malloc (m_SymbolsSize + 1);
|
||||
is.read (m_Symbols, m_SymbolsSize);
|
||||
m_Symbols [m_SymbolsSize] = 0;
|
||||
is.align();
|
||||
is.read (m_Addresses, m_nFrames * sizeof(void*));
|
||||
}
|
||||
|
||||
/// Writes the object to stream \p os.
|
||||
void CBacktrace::write (ostream& os) const
|
||||
{
|
||||
assert (os.aligned (alignof (m_Addresses[0])) && "Backtrace object contains pointers and must be void* aligned");
|
||||
os << m_nFrames << m_SymbolsSize;
|
||||
os.write (m_Symbols, m_SymbolsSize);
|
||||
os.align();
|
||||
os.write (m_Addresses, m_nFrames * sizeof(void*));
|
||||
}
|
||||
|
||||
/// Returns the size of the written object.
|
||||
size_t CBacktrace::stream_size (void) const
|
||||
{
|
||||
return (Align (stream_size_of (m_nFrames) +
|
||||
stream_size_of (m_SymbolsSize) +
|
||||
m_nFrames * sizeof(void*) +
|
||||
m_SymbolsSize));
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2006 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// bktrace.h
|
||||
//
|
||||
|
||||
#ifndef BKTRACE_H_63ABB1E4388CEDD975DBE58B57DE474F
|
||||
#define BKTRACE_H_63ABB1E4388CEDD975DBE58B57DE474F
|
||||
|
||||
#include "ulimits.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
class ostringstream;
|
||||
class istream;
|
||||
class ostream;
|
||||
|
||||
/// \class CBacktrace bktrace.h ustl.h
|
||||
///
|
||||
/// \brief Stores the backtrace from the point of construction.
|
||||
///
|
||||
/// The backtrace, or callstack, is the listing of functions called to
|
||||
/// reach the construction of this object. This is useful for debugging,
|
||||
/// to print the location of an error. To get meaningful output you'll
|
||||
/// need to use a debug build with symbols and with frame pointers. For
|
||||
/// GNU ld you will also need to link with the -rdynamic option to see
|
||||
/// actual function names instead of __gxx_personality0+0xF4800.
|
||||
///
|
||||
class CBacktrace {
|
||||
public:
|
||||
CBacktrace (void);
|
||||
CBacktrace (const CBacktrace& v);
|
||||
~CBacktrace (void);
|
||||
const CBacktrace& operator= (const CBacktrace& v);
|
||||
void text_write (ostringstream& os) const;
|
||||
void read (istream& is);
|
||||
void write (ostream& os) const;
|
||||
size_t stream_size (void) const;
|
||||
private:
|
||||
void GetSymbols (void);
|
||||
private:
|
||||
void* m_Addresses [64]; ///< Addresses of each function on the stack.
|
||||
char* m_Symbols; ///< Symbols corresponding to each address.
|
||||
uint32_t m_nFrames; ///< Number of addresses in m_Addresses.
|
||||
uint32_t m_SymbolsSize; ///< Size of m_Symbols.
|
||||
};
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
ALIGNOF(ustl::CBacktrace, sizeof(void*))
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
/* This file is part of bsconf - a configure replacement.
|
||||
*
|
||||
* This is the configuration file used by bsconf.c to specify information
|
||||
* specific to your project that it needs to substitute into files listed
|
||||
* in g_Files. Being a configuration file, this file can be used or
|
||||
* modified entirely without restriction. You should change all values
|
||||
* appropriately to the name of your project and its requirements. The
|
||||
* bsconf license does not apply to this file. It can and should be
|
||||
* treated as a template for the creation of your own configuration file.
|
||||
*
|
||||
* All substituted variable names are given without enclosing @@. For
|
||||
* example: "CC" will match "@CC@" in config.h.in and replace it with
|
||||
* "gcc" in config.h.
|
||||
*/
|
||||
|
||||
#include "uassert.h"
|
||||
|
||||
#define BSCONF_VERSION 0x03
|
||||
|
||||
#define PACKAGE_NAME "ustl"
|
||||
#define LIB_MAJOR "1"
|
||||
#define LIB_MINOR "0"
|
||||
#define LIB_BUILD "0"
|
||||
|
||||
#define PACKAGE_VERSION LIB_MAJOR "." LIB_MINOR
|
||||
#define PACKAGE_TARNAME PACKAGE_NAME
|
||||
#define PACKAGE_STRING PACKAGE_NAME " " PACKAGE_VERSION
|
||||
#define PACKAGE_BUGREPORT "Mike Sharov <msharov@users.sourceforge.net>"
|
||||
|
||||
static cpchar_t g_Files [] = {
|
||||
"Config.mk",
|
||||
"config.h",
|
||||
"ustl.spec"
|
||||
};
|
||||
|
||||
/* Values substitute @VARNAME@ */
|
||||
static cpchar_t g_EnvVars [] = {
|
||||
"CC",
|
||||
"LD",
|
||||
"CXX",
|
||||
"CPP",
|
||||
"HOME",
|
||||
"CXXFLAGS",
|
||||
"LDFLAGS",
|
||||
"CPPFLAGS",
|
||||
"LDFLAGS",
|
||||
"CFLAGS"
|
||||
};
|
||||
|
||||
/* VARIABLE PROGRAM HOW TO CALL IF NOT FOUND */
|
||||
static cpchar_t g_ProgVars [] = {
|
||||
"CC", "gcc", "gcc", "@CC@",
|
||||
"CC", "cc", "cc", "gcc",
|
||||
"CXX", "g++", "g++", "@CXX@",
|
||||
"CXX", "c++", "c++", "g++",
|
||||
"LD", "ld", "ld", "ld",
|
||||
"AR", "ar", "ar", "echo",
|
||||
"RANLIB", "ranlib", "ranlib", "touch",
|
||||
"DOXYGEN", "doxygen", "doxygen", "echo",
|
||||
"INSTALL", "install", "install -c", "cp"
|
||||
};
|
||||
|
||||
/* NAME IF NOT FOUND IF FOUND */
|
||||
static cpchar_t g_Headers [] = {
|
||||
"assert.h", "#undef HAVE_ASSERT_H", "#define HAVE_ASSERT_H 1",
|
||||
"ctype.h", "#undef HAVE_CTYPE_H", "#define HAVE_CTYPE_H 1",
|
||||
"errno.h", "#undef HAVE_ERRNO_H", "#define HAVE_ERRNO_H 1",
|
||||
"fcntl.h", "#undef HAVE_FCNTL_H", "#define HAVE_FCNTL_H 1",
|
||||
"float.h", "#undef HAVE_FLOAT_H", "#define HAVE_FLOAT_H 1",
|
||||
"inttypes.h", "#undef HAVE_INTTYPES_H", "#define HAVE_INTTYPES_H 1",
|
||||
"limits.h", "#undef HAVE_LIMITS_H", "#define HAVE_LIMITS_H 1",
|
||||
"locale.h", "#undef HAVE_LOCALE_H", "#define HAVE_LOCALE_H 1",
|
||||
"malloc.h", "#undef HAVE_MALLOC_H", "#define HAVE_MALLOC_H 1",
|
||||
"alloca.h", "#undef HAVE_ALLOCA_H", "#define HAVE_ALLOCA_H 1",
|
||||
"memory.h", "#undef HAVE_MEMORY_H", "#define HAVE_MEMORY_H 1",
|
||||
"signal.h", "#undef HAVE_SIGNAL_H", "#define HAVE_SIGNAL_H 1",
|
||||
"stdarg.h", "#undef HAVE_STDARG_H", "#define HAVE_STDARG_H 1",
|
||||
"stddef.h", "#undef HAVE_STDDEF_H", "#define HAVE_STDDEF_H 1",
|
||||
"stdint.h", "#undef HAVE_STDINT_H", "#define HAVE_STDINT_H 1",
|
||||
"stdio.h", "#undef HAVE_STDIO_H", "#define HAVE_STDIO_H 1",
|
||||
"stdlib.h", "#undef HAVE_STDLIB_H", "#define HAVE_STDLIB_H 1",
|
||||
"string.h", "#undef HAVE_STRING_H", "#define HAVE_STRING_H 1",
|
||||
"strings.h", "#undef HAVE_STRINGS_H", "#define HAVE_STRINGS_H 1",
|
||||
"sys/stat.h", "#undef HAVE_SYS_STAT_H", "#define HAVE_SYS_STAT_H 1",
|
||||
"sys/types.h", "#undef HAVE_SYS_TYPES_H", "#define HAVE_SYS_TYPES_H 1",
|
||||
"sys/wait.h", "#undef HAVE_SYS_WAIT_H", "#define HAVE_SYS_WAIT_H 1",
|
||||
"time.h", "#undef HAVE_TIME_H", "#define HAVE_TIME_H 1",
|
||||
"unistd.h", "#undef HAVE_UNISTD_H", "#define HAVE_UNISTD_H 1",
|
||||
"math.h", "#undef HAVE_MATH_H", "#define HAVE_MATH_H 1",
|
||||
"stdlib.h", "#undef HAVE_STDLIB_H", "#define HAVE_STDLIB_H 1"
|
||||
};
|
||||
|
||||
/* NAME IF NOT FOUND IF FOUND */
|
||||
static cpchar_t g_Libs [] = {
|
||||
"supc++", "", "-lsupc++",
|
||||
#if __GNUC__ >= 4
|
||||
"gcc", "-lgcc_s", "-lgcc_s",
|
||||
"gcc_eh", "", "",
|
||||
#elif __GNUC__ >= 3
|
||||
"gcc", "-lgcc_s", "-lgcc",
|
||||
"gcc_eh", "-lgcc_s", "-lgcc_eh",
|
||||
#else
|
||||
"gcc", "", "-lgcc",
|
||||
"gcc_eh", "", "",
|
||||
#endif
|
||||
"SystemStubs", "", "-lSystemStubs", /* For MacOS 10.4+ */
|
||||
"c", "", "-lc"
|
||||
};
|
||||
|
||||
/* NAME IF NOT FOUND IF FOUND */
|
||||
static cpchar_t g_Functions [] = {
|
||||
"atexit", "#undef HAVE_ATEXIT", "#define HAVE_ATEXIT 1",
|
||||
"malloc", "#undef HAVE_MALLOC\n", "#define HAVE_MALLOC 1\n",
|
||||
"memchr", "#undef HAVE_MEMCHR", "#define HAVE_MEMCHR 1",
|
||||
"memmove", "#undef HAVE_MEMMOVE", "#define HAVE_MEMMOVE 1",
|
||||
"memset", "#undef HAVE_MEMSET", "#define HAVE_MEMSET 1",
|
||||
"ptrdiff_t", "#undef HAVE_PTRDIFF_T", "#define HAVE_PTRDIFF_T 1",
|
||||
"strerror", "#undef HAVE_STRERROR", "#define HAVE_STRERROR 1",
|
||||
"strsignal", "#undef HAVE_STRSIGNAL", "#define HAVE_STRSIGNAL 1",
|
||||
"strtol", "#undef HAVE_STRTOL", "#define HAVE_STRTOL 1",
|
||||
#if __GNUC__ >= 3
|
||||
"round", "#undef HAVE_ROUND", "#define HAVE_ROUND 1",
|
||||
#endif
|
||||
"strrchr", "#undef HAVE_STRRCHR", "#define HAVE_STRRCHR 1",
|
||||
"__va_copy", "#undef HAVE_VA_COPY", "#define HAVE_VA_COPY 1"
|
||||
};
|
||||
|
||||
/* NAME WITHOUT TEXT WITH TEXT */
|
||||
static cpchar_t g_Components [] = {
|
||||
"shared", "#BUILD_SHARED\t= 1", "BUILD_SHARED\t= 1 ",
|
||||
"static", "#BUILD_STATIC\t= 1", "BUILD_STATIC\t= 1 ",
|
||||
"debug", "#DEBUG\t\t= 1", "DEBUG\t\t= 1 ",
|
||||
"bounds", "#undef WANT_STREAM_BOUNDS_CHECKING", "#define WANT_STREAM_BOUNDS_CHECKING 1 ",
|
||||
"fastcopy", "#undef WANT_UNROLLED_COPY", "#define WANT_UNROLLED_COPY 1 ",
|
||||
#if __GNUC__ >= 3 && (__i386__ || __x86_64__) && !sun
|
||||
"mmx", "#undef WANT_MMX", "#define WANT_MMX 1 ",
|
||||
#endif
|
||||
"libstdc++", "#define WITHOUT_LIBSTDCPP 1", "#undef WITHOUT_LIBSTDCPP",
|
||||
"libstdc++", "NOLIBSTDCPP\t= -nodefaultlibs ", "#NOLIBSTDCPP\t= -nodefaultlibs"
|
||||
};
|
||||
|
||||
/* Parallel to g_Components */
|
||||
static SComponentInfo g_ComponentInfos [VectorSize(g_Components) / 3] = {
|
||||
{ 1, "Builds the shared library (if supported by the OS)" },
|
||||
{ 0, "Builds the static library" },
|
||||
{ 0, "Compiles the library with debugging information" },
|
||||
{ 1, "Disable runtime bounds checking on stream reads/writes" },
|
||||
{ 1, "Disable specializations for copy/fill" },
|
||||
#if __GNUC__ >= 3 && (__i386__ || __x86_64__) && !sun
|
||||
{ 1, "Disable use of MMX/SSE/3dNow! instructions" },
|
||||
#endif
|
||||
#if __GNUC__ >= 3
|
||||
{ 0, "Link with libstdc++" },
|
||||
{ 0, "" }
|
||||
#else
|
||||
{ 1, "" },
|
||||
{ 1, "" }
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Substitutes names like @PACKAGE_NAME@ with the second field */
|
||||
static cpchar_t g_CustomVars [] = {
|
||||
"PACKAGE_NAME", PACKAGE_NAME,
|
||||
"PACKAGE_VERSION", PACKAGE_VERSION,
|
||||
"PACKAGE_TARNAME", PACKAGE_TARNAME,
|
||||
"PACKAGE_STRING", PACKAGE_STRING,
|
||||
"PACKAGE_BUGREPORT", PACKAGE_BUGREPORT,
|
||||
"LIBNAME", PACKAGE_NAME,
|
||||
"LIB_MAJOR", LIB_MAJOR,
|
||||
"LIB_MINOR", LIB_MINOR,
|
||||
"LIB_BUILD", LIB_BUILD
|
||||
};
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// cmemlink.cc
|
||||
//
|
||||
// See cmemlink.h for documentation.
|
||||
//
|
||||
|
||||
#include "cmemlink.h"
|
||||
#include "ofstream.h"
|
||||
#include "strmsize.h"
|
||||
#include "ualgo.h"
|
||||
#include "uassert.h"
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
#include <stdio.h>
|
||||
#undef CPU_HAS_MMX
|
||||
#endif
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// \brief Attaches the object to pointer \p p of size \p n.
|
||||
///
|
||||
/// If \p p is NULL and \p n is non-zero, bad_alloc is thrown and current
|
||||
/// state remains unchanged.
|
||||
///
|
||||
void cmemlink::link (const void* p, size_type n)
|
||||
{
|
||||
if (!p && n)
|
||||
#if PLATFORM_ANDROID
|
||||
printf("bad alloc\n");
|
||||
#else /* !PLATFORM_ANDROID */
|
||||
throw bad_alloc (n);
|
||||
#endif
|
||||
unlink();
|
||||
relink (p, n);
|
||||
}
|
||||
|
||||
/// Writes the object to stream \p os
|
||||
void cmemlink::write (ostream& os) const
|
||||
{
|
||||
const written_size_type sz (size());
|
||||
assert (sz == size() && "No support for writing memblocks larger than 4G");
|
||||
os << sz;
|
||||
os.write (cdata(), sz);
|
||||
os.align (alignof (sz));
|
||||
}
|
||||
|
||||
/// Writes the object to stream \p os
|
||||
void cmemlink::text_write (ostringstream& os) const
|
||||
{
|
||||
os.write (begin(), readable_size());
|
||||
}
|
||||
|
||||
/// Returns the number of bytes required to write this object to a stream.
|
||||
cmemlink::size_type cmemlink::stream_size (void) const
|
||||
{
|
||||
const written_size_type sz (size());
|
||||
return (Align (stream_size_of (sz) + sz, alignof(sz)));
|
||||
}
|
||||
|
||||
/// Writes the data to file \p "filename".
|
||||
void cmemlink::write_file (const char* filename, int mode) const
|
||||
{
|
||||
fstream f;
|
||||
f.exceptions (fstream::allbadbits);
|
||||
f.open (filename, fstream::out | fstream::trunc, mode);
|
||||
f.write (cdata(), readable_size());
|
||||
f.close();
|
||||
}
|
||||
|
||||
/// swaps the contents with \p l
|
||||
void cmemlink::swap (cmemlink& l)
|
||||
{
|
||||
#if CPU_HAS_MMX && SIZE_OF_POINTER == 4
|
||||
asm (
|
||||
"movq %0, %%mm0\n\t"
|
||||
"movq %2, %%mm1\n\t"
|
||||
"movq %%mm0, %2\n\t"
|
||||
"movq %%mm1, %0"
|
||||
: "=m"(m_Data), "=m"(m_Size), "=m"(l.m_Data), "=m"(l.m_Size)
|
||||
:
|
||||
: "mm0", "mm1", "st", "st(1)");
|
||||
simd::reset_mmx();
|
||||
#elif CPU_HAS_SSE && SIZE_OF_POINTER == 8
|
||||
asm (
|
||||
"movups %0, %%xmm0\n\t"
|
||||
"movups %2, %%xmm1\n\t"
|
||||
"movups %%xmm0, %2\n\t"
|
||||
"movups %%xmm1, %0"
|
||||
: "=m"(m_Data), "=m"(m_Size), "=m"(l.m_Data), "=m"(l.m_Size)
|
||||
:
|
||||
: "xmm0", "xmm1");
|
||||
#else
|
||||
::ustl::swap (m_Data, l.m_Data);
|
||||
::ustl::swap (m_Size, l.m_Size);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Compares to memory block pointed by l. Size is compared first.
|
||||
bool cmemlink::operator== (const cmemlink& l) const
|
||||
{
|
||||
return (l.m_Size == m_Size &&
|
||||
(l.m_Data == m_Data || 0 == memcmp (l.m_Data, m_Data, m_Size)));
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// cmemlink.h
|
||||
//
|
||||
|
||||
#ifndef CMEMLINK_H_7CFAB32C5C6732ED29B34EF00EA40A12
|
||||
#define CMEMLINK_H_7CFAB32C5C6732ED29B34EF00EA40A12
|
||||
|
||||
#include "ualgobase.h"
|
||||
|
||||
/// The ustl namespace contains all ustl classes and algorithms.
|
||||
namespace ustl {
|
||||
|
||||
class istream;
|
||||
class ostream;
|
||||
class ostringstream;
|
||||
|
||||
/// \class cmemlink cmemlink.h ustl.h
|
||||
/// \ingroup MemoryManagement
|
||||
///
|
||||
/// \brief A read-only pointer to a sized block of memory.
|
||||
///
|
||||
/// Use this class the way you would a const pointer to an allocated unstructured block.
|
||||
/// The pointer and block size are available through member functions and cast operator.
|
||||
///
|
||||
/// Example usage:
|
||||
///
|
||||
/// \code
|
||||
/// void* p = malloc (46721);
|
||||
/// cmemlink a, b;
|
||||
/// a.link (p, 46721);
|
||||
/// assert (a.size() == 46721));
|
||||
/// b = a;
|
||||
/// assert (b.size() == 46721));
|
||||
/// assert (b.DataAt(34) == a.DataAt(34));
|
||||
/// assert (0 == memcmp (a, b, 12));
|
||||
/// \endcode
|
||||
///
|
||||
class cmemlink {
|
||||
public:
|
||||
typedef char value_type;
|
||||
typedef const value_type* pointer;
|
||||
typedef const value_type* const_pointer;
|
||||
typedef value_type reference;
|
||||
typedef value_type const_reference;
|
||||
typedef size_t size_type;
|
||||
typedef uint32_t written_size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef const_pointer const_iterator;
|
||||
typedef const_iterator iterator;
|
||||
typedef const cmemlink& rcself_t;
|
||||
public:
|
||||
inline cmemlink (void) : m_Data (NULL), m_Size (0) { }
|
||||
inline cmemlink (const void* p, size_type n) : m_Data (const_pointer(p)), m_Size (n) { assert (p || !n); }
|
||||
inline cmemlink (const cmemlink& l) : m_Data (l.m_Data), m_Size (l.m_Size) {}
|
||||
inline virtual ~cmemlink (void) {}
|
||||
void link (const void* p, size_type n);
|
||||
OVERLOAD_POINTER_AND_SIZE_T_V2(link, const void*)
|
||||
inline void link (const cmemlink& l) { link (l.begin(), l.size()); }
|
||||
inline void link (const void* first, const void* last) { link (first, distance (first, last)); }
|
||||
inline void relink (const void* p, size_type n);
|
||||
inline virtual void unlink (void) { m_Data = NULL; m_Size = 0; }
|
||||
inline rcself_t operator= (const cmemlink& l) { link (l); return (*this); }
|
||||
bool operator== (const cmemlink& l) const;
|
||||
void swap (cmemlink& l);
|
||||
inline size_type size (void) const { return (m_Size); }
|
||||
inline size_type max_size (void) const { return (size()); }
|
||||
inline size_type readable_size (void) const { return (size()); }
|
||||
inline bool empty (void) const { return (!size()); }
|
||||
inline const_pointer cdata (void) const { return (m_Data); }
|
||||
inline iterator begin (void) const { return (iterator (cdata())); }
|
||||
inline iterator iat (size_type i) const { assert (i <= size()); return (begin() + i); }
|
||||
inline iterator end (void) const { return (iat (size())); }
|
||||
inline void resize (size_type n) { m_Size = n; }
|
||||
inline void read (istream&) { assert (!"ustl::cmemlink is a read-only object."); }
|
||||
void write (ostream& os) const;
|
||||
size_type stream_size (void) const;
|
||||
void text_write (ostringstream& os) const;
|
||||
void write_file (const char* filename, int mode = 0644) const;
|
||||
private:
|
||||
const_pointer m_Data; ///< Pointer to the data block (const)
|
||||
size_type m_Size; ///< size of the data block
|
||||
};
|
||||
|
||||
/// A fast alternative to link which can be used when relinking to the same block (i.e. when it is resized)
|
||||
inline void cmemlink::relink (const void* p, size_type n)
|
||||
{
|
||||
m_Data = reinterpret_cast<const_pointer>(p);
|
||||
m_Size = n;
|
||||
}
|
||||
|
||||
/// Use with cmemlink-derived classes to link to a static array
|
||||
#define static_link(v) link (VectorBlock(v))
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,296 +0,0 @@
|
||||
// config.h
|
||||
//
|
||||
// Autogenerated from config.h.in by bsconf.
|
||||
//
|
||||
|
||||
#ifndef CONFIG_H_01E33670634DAAC779EE5FF41CCBB36F
|
||||
#define CONFIG_H_01E33670634DAAC779EE5FF41CCBB36F
|
||||
|
||||
#include "uassert.h"
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
|
||||
#include <utils/Endian.h>
|
||||
|
||||
// Byte order macros, converted in utypes.h
|
||||
#define USTL_LITTLE_ENDIAN __LITTLE_ENDIAN
|
||||
#define USTL_BIG_ENDIAN __BIG_ENDIAN
|
||||
#define USTL_BYTE_ORDER __BYTE_ORDER
|
||||
|
||||
#if !defined NDEBUG
|
||||
#define NDEBUG
|
||||
#endif
|
||||
#else /* !PLATFORM_ANDROID */
|
||||
// Byte order macros, converted in utypes.h
|
||||
#define USTL_LITTLE_ENDIAN 4321
|
||||
#define USTL_BIG_ENDIAN 1234
|
||||
#define USTL_BYTE_ORDER USTL_LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
// Define to the one symbol short name of this package.
|
||||
#define USTL_NAME "ustl"
|
||||
// Define to the full name and version of this package.
|
||||
#define USTL_STRING "ustl 1.0"
|
||||
// Define to the version of this package.
|
||||
#define USTL_VERSION 0x100
|
||||
// Define to the address where bug reports for this package should be sent.
|
||||
#define USTL_BUGREPORT "Mike Sharov <msharov@users.sourceforge.net>"
|
||||
|
||||
/// Define to 1 if you want stream operations to throw exceptions on
|
||||
/// insufficient data or insufficient space. All these errors should
|
||||
/// be preventable in output code; the input code should verify the
|
||||
/// data in a separate step. It slows down stream operations a lot,
|
||||
/// but it's your call. By default only debug builds throw.
|
||||
///
|
||||
#undef WANT_STREAM_BOUNDS_CHECKING
|
||||
|
||||
#if !defined(WANT_STREAM_BOUNDS_CHECKING) && !defined(NDEBUG)
|
||||
#define WANT_STREAM_BOUNDS_CHECKING 1
|
||||
#endif
|
||||
|
||||
/// Define to 1 if you want to build without libstdc++
|
||||
#define WITHOUT_LIBSTDCPP 1
|
||||
|
||||
/// Define GNU extensions if unavailable.
|
||||
#ifndef __GNUC__
|
||||
/// GCC (and some other compilers) define '__attribute__'; ustl is using this
|
||||
/// macro to alert the compiler to flag inconsistencies in printf/scanf-like
|
||||
/// function calls. Just in case '__attribute__' isn't defined, make a dummy.
|
||||
///
|
||||
#ifndef __attribute__
|
||||
#define __attribute__(p)
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||
#define DLL_EXPORT __attribute__((visibility("default")))
|
||||
#define DLL_LOCAL __attribute__((visibility("hidden")))
|
||||
#else
|
||||
#define DLL_EXPORT
|
||||
#define DLL_LOCAL
|
||||
#endif
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3 && __i386__
|
||||
/// GCC 3+ supports the prefetch directive, which some CPUs use to improve caching
|
||||
#define prefetch(p,rw,loc) __builtin_prefetch(p,rw,loc)
|
||||
#else
|
||||
#define prefetch(p,rw,loc)
|
||||
#endif
|
||||
#if !defined(__GNUC__) || __GNUC__ < 3
|
||||
/// __alignof__ returns the recommended alignment for the type
|
||||
#define __alignof__(v) min(sizeof(v), sizeof(void*))
|
||||
#endif
|
||||
|
||||
/// Define to 1 if you have the `atexit' function.
|
||||
#define HAVE_ATEXIT 1
|
||||
|
||||
/// Define to 1 if you have the <assert.h> header file.
|
||||
#define HAVE_ASSERT_H 1
|
||||
|
||||
/// Define to 1 if you have the <ctype.h> header file.
|
||||
#define HAVE_CTYPE_H 1
|
||||
|
||||
/// Define to 1 if you have the <errno.h> header file.
|
||||
#define HAVE_ERRNO_H 1
|
||||
|
||||
/// Define to 1 if you have the <fcntl.h> header file.
|
||||
#define HAVE_FCNTL_H 1
|
||||
|
||||
/// Define to 1 if you have the <float.h> header file.
|
||||
#define HAVE_FLOAT_H 1
|
||||
|
||||
/// Define to 1 if you have the <inttypes.h> header file.
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/// Define to 1 if you have the <limits.h> header file.
|
||||
#define HAVE_LIMITS_H 1
|
||||
|
||||
/// Define to 1 if you have the <locale.h> header file.
|
||||
#define HAVE_LOCALE_H 1
|
||||
|
||||
/// Define to 1 if your system has a working `malloc' function.
|
||||
#define HAVE_MALLOC 1
|
||||
|
||||
// Define to 1 if you have the <malloc.h> header file.
|
||||
#undef HAVE_MALLOC_H
|
||||
|
||||
// Define to 1 if you have the <alloca.h> header file.
|
||||
#define HAVE_ALLOCA_H 1
|
||||
|
||||
// Define to 1 if you have the `memchr' function.
|
||||
#define HAVE_MEMCHR 1
|
||||
|
||||
// Define to 1 if you have the `memmove' function.
|
||||
#define HAVE_MEMMOVE 1
|
||||
|
||||
// Define to 1 if you have the <memory.h> header file.
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
// Define to 1 if you have the `memset' function.
|
||||
#define HAVE_MEMSET 1
|
||||
|
||||
// Define to 1 if the system has the type `ptrdiff_t'.
|
||||
#define HAVE_PTRDIFF_T 1
|
||||
|
||||
// Define to 1 if you have the <signal.h> header file.
|
||||
#define HAVE_SIGNAL_H 1
|
||||
|
||||
// Define to 1 if you have the __va_copy function
|
||||
#define HAVE_VA_COPY 1
|
||||
|
||||
// Define to 1 if `stat' has the bug that it succeeds when given the
|
||||
// zero-length file name argument.
|
||||
/* #undef HAVE_STAT_EMPTY_STRING_BUG */
|
||||
|
||||
// Define to 1 if you have the <stdarg.h> header file.
|
||||
#define HAVE_STDARG_H 1
|
||||
|
||||
// Define to 1 if you have the <stddef.h> header file.
|
||||
#define HAVE_STDDEF_H 1
|
||||
|
||||
// Define to 1 if you have the <stdint.h> header file.
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
// Define to 1 if you have the <stdio.h> header file.
|
||||
#define HAVE_STDIO_H 1
|
||||
|
||||
// Define to 1 if you have the <stdlib.h> header file.
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
// Define to 1 if you have the `strerror' function.
|
||||
#define HAVE_STRERROR 1
|
||||
|
||||
// Define to 1 if you have the <strings.h> header file.
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
// Define to 1 if you have the <string.h> header file.
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
// Define to 1 if you have the `strrchr' function.
|
||||
#define HAVE_STRRCHR 1
|
||||
|
||||
// Define to 1 if you have the `strsignal' function.
|
||||
#undef HAVE_STRSIGNAL
|
||||
|
||||
// Define to 1 if you have the `strtol' function.
|
||||
#define HAVE_STRTOL 1
|
||||
|
||||
// Define to 1 if you have the <sys/stat.h> header file.
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
// Define to 1 if you have the <sys/types.h> header file.
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
// Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible.
|
||||
#define HAVE_SYS_WAIT_H 1
|
||||
|
||||
// Define to 1 if you have the <time.h> header file.
|
||||
#define HAVE_TIME_H 1
|
||||
|
||||
// Define to 1 if you have the <unistd.h> header file.
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
// Define to 1 if you have the <math.h> header file.
|
||||
#define HAVE_MATH_H 1
|
||||
|
||||
// Define to 1 if you have the rintf function. Will use rint otherwise.
|
||||
#undef HAVE_RINTF
|
||||
|
||||
// STDC_HEADERS is defined to 1 on sane systems.
|
||||
#if defined(HAVE_ASSERT_H) && defined(HAVE_CTYPE_H) &&\
|
||||
defined(HAVE_ERRNO_H) && defined(HAVE_FLOAT_H) &&\
|
||||
defined(HAVE_LIMITS_H) && defined(HAVE_LOCALE_H) &&\
|
||||
defined(HAVE_MATH_H) && defined(HAVE_SIGNAL_H) &&\
|
||||
defined(HAVE_STDARG_H) && defined(HAVE_STDDEF_H) &&\
|
||||
defined(HAVE_STDIO_H) && defined(HAVE_STDLIB_H) &&\
|
||||
defined(HAVE_STRING_H) && defined(HAVE_TIME_H)
|
||||
#define STDC_HEADERS 1
|
||||
#endif
|
||||
|
||||
// STDC_HEADERS is defined to 1 on unix systems.
|
||||
#if defined(HAVE_FCNTL_H) && defined(HAVE_SYS_STAT_H) && defined(HAVE_UNISTD_H)
|
||||
#define STDUNIX_HEADERS 1
|
||||
#endif
|
||||
|
||||
// Define to 1 if `lstat' dereferences a symlink specified with a trailing slash.
|
||||
#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
|
||||
|
||||
// Define to 1 if your compiler treats char as a separate type along with
|
||||
// signed char and unsigned char. This will create overloads for char.
|
||||
#define HAVE_THREE_CHAR_TYPES 1
|
||||
|
||||
// Define as the return type of signal handlers (`int' or `void').
|
||||
#define RETSIGTYPE void
|
||||
|
||||
// Define to 1 if you have 64 bit types available
|
||||
#define HAVE_INT64_T 1
|
||||
|
||||
// Define to 1 if you have the long long type
|
||||
#undef HAVE_LONG_LONG
|
||||
|
||||
// Define to 1 if you want unrolled specializations for fill and copy
|
||||
#define WANT_UNROLLED_COPY 1
|
||||
|
||||
// Define to 1 if you want to use MMX/SSE/3dNow! processor instructions
|
||||
#undef WANT_MMX
|
||||
|
||||
// Define to byte sizes of types
|
||||
#define SIZE_OF_CHAR 1
|
||||
#define SIZE_OF_SHORT 2
|
||||
#define SIZE_OF_INT 4
|
||||
#define SIZE_OF_LONG 4
|
||||
#define SIZE_OF_LONG_LONG 8
|
||||
#define SIZE_OF_POINTER 4
|
||||
#define SIZE_OF_SIZE_T 4
|
||||
#define SIZE_OF_BOOL SIZE_OF_LONG
|
||||
#if SIZE_OF_SIZE_T == SIZE_OF_LONG
|
||||
#define SIZE_T_IS_LONG 1
|
||||
#else
|
||||
#define SIZE_T_IS_LONG 0
|
||||
#endif
|
||||
|
||||
// Extended CPU capabilities
|
||||
#undef CPU_HAS_FPU
|
||||
#undef CPU_HAS_EXT_DEBUG
|
||||
#undef CPU_HAS_TIMESTAMPC
|
||||
#undef CPU_HAS_MSR
|
||||
#undef CPU_HAS_CMPXCHG8
|
||||
#undef CPU_HAS_APIC
|
||||
#undef CPU_HAS_SYSCALL
|
||||
#undef CPU_HAS_MTRR
|
||||
#undef CPU_HAS_CMOV
|
||||
#undef CPU_HAS_FCMOV
|
||||
#if WANT_MMX
|
||||
#undef CPU_HAS_MMX
|
||||
#undef CPU_HAS_FXSAVE
|
||||
#undef CPU_HAS_SSE
|
||||
#undef CPU_HAS_SSE2
|
||||
#undef CPU_HAS_SSE3
|
||||
#undef CPU_HAS_EXT_3DNOW
|
||||
#undef CPU_HAS_3DNOW
|
||||
#endif
|
||||
|
||||
// GCC vector extensions
|
||||
#if defined(CPU_HAS_MMX) || defined(CPU_HAS_SSE)
|
||||
#define HAVE_VECTOR_EXTENSIONS 1
|
||||
#endif
|
||||
|
||||
#if CPU_HAS_SSE && defined(__GNUC__)
|
||||
#define __sse_align __attribute__((aligned(16)))
|
||||
#else
|
||||
#define __sse_align
|
||||
#endif
|
||||
|
||||
// Define to empty if `const' does not conform to ANSI C.
|
||||
/* #define const */
|
||||
|
||||
// Define as `__inline' if that's what the C compiler calls it, or to nothing
|
||||
// if it is not supported.
|
||||
/* #define inline __inline */
|
||||
|
||||
// Define to `long' if <sys/types.h> does not define.
|
||||
/* typedef long off_t; */
|
||||
|
||||
// Define to `unsigned' if <sys/types.h> does not define.
|
||||
/* typedef long size_t; */
|
||||
|
||||
#endif // CONFIG_H_01E33670634DAAC779EE5FF41CCBB36F
|
||||
|
||||
@@ -1,282 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// file.cc
|
||||
//
|
||||
|
||||
#include "fstream.h"
|
||||
#include "uassert.h"
|
||||
#include "uexception.h"
|
||||
#include "uutility.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// Default constructor.
|
||||
fstream::fstream (void)
|
||||
: ios_base (),
|
||||
m_fd (-1),
|
||||
m_Filename ()
|
||||
{
|
||||
}
|
||||
|
||||
/// Opens \p filename in \p mode.
|
||||
fstream::fstream (const char* filename, openmode mode)
|
||||
: ios_base (),
|
||||
m_fd (-1),
|
||||
m_Filename ()
|
||||
{
|
||||
open (filename, mode);
|
||||
}
|
||||
|
||||
/// Attaches to \p nfd of \p filename.
|
||||
fstream::fstream (int nfd, const char* filename)
|
||||
: ios_base (),
|
||||
m_fd (-1),
|
||||
m_Filename ()
|
||||
{
|
||||
attach (nfd, filename);
|
||||
}
|
||||
|
||||
/// Destructor. Closes if still open, but without throwing.
|
||||
fstream::~fstream (void) throw()
|
||||
{
|
||||
clear (goodbit);
|
||||
exceptions (goodbit);
|
||||
close();
|
||||
assert (!(rdstate() & badbit) && "close failed in the destructor! This may lead to loss of user data. Please call close() manually and either enable exceptions or check the badbit.");
|
||||
}
|
||||
|
||||
/// Sets state \p s and throws depending on the exception setting.
|
||||
void fstream::set_and_throw (iostate s, const char* op)
|
||||
{
|
||||
if (ios_base::set_and_throw (s))
|
||||
#if PLATFORM_ANDROID
|
||||
printf("file_exception\n");
|
||||
#else /* !PLATFORM_ANDROID */
|
||||
throw file_exception (op, name());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Attaches to the given \p nfd.
|
||||
void fstream::attach (int nfd, const char* filename)
|
||||
{
|
||||
assert (filename && "Don't do that");
|
||||
clear (goodbit);
|
||||
if (nfd < 0 && ios_base::set_and_throw (badbit))
|
||||
#if PLATFORM_ANDROID
|
||||
printf("file exception\n");
|
||||
#else /* !PLATFORM_ANDROID */
|
||||
throw file_exception ("open", filename);
|
||||
#endif
|
||||
close();
|
||||
m_fd = nfd;
|
||||
m_Filename = filename;
|
||||
}
|
||||
|
||||
/// Detaches from the current fd.
|
||||
void fstream::detach (void)
|
||||
{
|
||||
m_fd = -1;
|
||||
m_Filename.clear();
|
||||
}
|
||||
|
||||
/// Converts openmode bits into libc open flags.
|
||||
/*static*/ int fstream::om_to_flags (openmode m)
|
||||
{
|
||||
static const int s_OMFlags [nombits] = {
|
||||
0, // in
|
||||
O_CREAT, // out
|
||||
O_APPEND, // app
|
||||
O_APPEND, // ate
|
||||
0, // binary
|
||||
O_TRUNC, // trunc
|
||||
O_NONBLOCK, // nonblock
|
||||
0, // nocreate
|
||||
O_NOCTTY // noctty
|
||||
};
|
||||
int flags = (m - 1) & O_ACCMODE; // in and out
|
||||
for (uoff_t i = 0; i < VectorSize(s_OMFlags); ++ i)
|
||||
if (m & (1 << i))
|
||||
flags |= s_OMFlags[i];
|
||||
if (m & nocreate)
|
||||
flags &= ~O_CREAT;
|
||||
return (flags);
|
||||
}
|
||||
|
||||
/// \brief Opens \p filename in the given mode.
|
||||
/// \warning The string at \p filename must exist until the object is closed.
|
||||
void fstream::open (const char* filename, openmode mode, mode_t perms)
|
||||
{
|
||||
int nfd = ::open (filename, om_to_flags(mode), perms);
|
||||
attach (nfd, filename);
|
||||
}
|
||||
|
||||
/// Closes the file and throws on error.
|
||||
void fstream::close (void)
|
||||
{
|
||||
if (m_fd >= 0 && ::close(m_fd))
|
||||
set_and_throw (badbit | failbit, "close");
|
||||
detach();
|
||||
}
|
||||
|
||||
/// Moves the current file position to \p n.
|
||||
off_t fstream::seek (off_t n, seekdir whence)
|
||||
{
|
||||
off_t p = lseek (m_fd, n, whence);
|
||||
if (p < 0)
|
||||
set_and_throw (failbit, "seek");
|
||||
return (p);
|
||||
}
|
||||
|
||||
/// Returns the current file position.
|
||||
off_t fstream::pos (void) const
|
||||
{
|
||||
return (lseek (m_fd, 0, SEEK_CUR));
|
||||
}
|
||||
|
||||
/// Reads \p n bytes into \p p.
|
||||
off_t fstream::read (void* p, off_t n)
|
||||
{
|
||||
off_t br (0);
|
||||
while (br < n && good())
|
||||
br += readsome (advance (p, br), n - br);
|
||||
return (br);
|
||||
}
|
||||
|
||||
/// Reads at most \p n bytes into \p p, stopping when it feels like it.
|
||||
off_t fstream::readsome (void* p, off_t n)
|
||||
{
|
||||
ssize_t brn;
|
||||
do { brn = ::read (m_fd, p, n); } while (brn < 0 && errno == EINTR);
|
||||
if (brn > 0)
|
||||
return (brn);
|
||||
if (brn < 0 && errno != EAGAIN)
|
||||
set_and_throw (failbit, "read");
|
||||
if (!brn && ios_base::set_and_throw (eofbit | failbit))
|
||||
#if PLATFORM_ANDROID
|
||||
printf("stream_bounds_exception\n");
|
||||
#else /* !PLATFORM_ANDROID */
|
||||
throw stream_bounds_exception ("read", name(), pos(), n, 0);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
/// Writes \p n bytes from \p p.
|
||||
off_t fstream::write (const void* p, off_t n)
|
||||
{
|
||||
off_t btw (n);
|
||||
while (btw) {
|
||||
const off_t bw (n - btw);
|
||||
ssize_t bwn = ::write (m_fd, advance(p,bw), btw);
|
||||
if (bwn > 0)
|
||||
btw -= bwn;
|
||||
else if (!bwn) {
|
||||
if (ios_base::set_and_throw (eofbit | failbit))
|
||||
#if PLATFORM_ANDROID
|
||||
printf("stream_bounds_exception\n");
|
||||
#else /* !PLATFORM_ANDROID */
|
||||
throw stream_bounds_exception ("write", name(), pos() - bw, n, bw);
|
||||
#endif
|
||||
break;
|
||||
} else if (errno != EINTR) {
|
||||
if (errno != EAGAIN)
|
||||
set_and_throw (failbit, "write");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (n - btw);
|
||||
}
|
||||
|
||||
/// Returns the file size.
|
||||
off_t fstream::size (void) const
|
||||
{
|
||||
struct stat st;
|
||||
st.st_size = 0;
|
||||
stat (st);
|
||||
return (st.st_size);
|
||||
}
|
||||
|
||||
/// Synchronizes the file's data and status with the disk.
|
||||
void fstream::sync (void)
|
||||
{
|
||||
if (fsync (m_fd))
|
||||
set_and_throw (failbit, "sync");
|
||||
}
|
||||
|
||||
/// Get the stat structure.
|
||||
void fstream::stat (struct stat& rs) const
|
||||
{
|
||||
if (fstat (m_fd, &rs))
|
||||
#if PLATFORM_ANDROID
|
||||
printf("file_exception\n");
|
||||
#else
|
||||
throw file_exception ("stat", name());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Calls the given ioctl. Use IOCTLID macro to pass in both \p name and \p request.
|
||||
int fstream::ioctl (const char* rname, int request, long argument)
|
||||
{
|
||||
int rv = ::ioctl (m_fd, request, argument);
|
||||
if (rv < 0)
|
||||
set_and_throw (failbit, rname);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/// Calls the given fcntl. Use FCNTLID macro to pass in both \p name and \p request.
|
||||
int fstream::fcntl (const char* rname, int request, long argument)
|
||||
{
|
||||
int rv = ::fcntl (m_fd, request, argument);
|
||||
if (rv < 0)
|
||||
set_and_throw (failbit, rname);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/// Memory-maps the file and returns a link to it.
|
||||
memlink fstream::mmap (off_t n, off_t offset)
|
||||
{
|
||||
void* result = ::mmap (NULL, n, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, offset);
|
||||
if (result == MAP_FAILED)
|
||||
set_and_throw (failbit, "mmap");
|
||||
return (memlink (result, n));
|
||||
}
|
||||
|
||||
/// Unmaps a memory-mapped area.
|
||||
void fstream::munmap (memlink& l)
|
||||
{
|
||||
if (::munmap (l.data(), l.size()))
|
||||
set_and_throw (failbit, "munmap");
|
||||
l.unlink();
|
||||
}
|
||||
|
||||
/// Synchronizes a memory-mapped area.
|
||||
void fstream::msync (memlink& l)
|
||||
{
|
||||
if (::msync (l.data(), l.size(), MS_ASYNC | MS_INVALIDATE))
|
||||
set_and_throw (failbit, "msync");
|
||||
}
|
||||
|
||||
void fstream::set_nonblock (bool v)
|
||||
{
|
||||
int curf = fcntl (FCNTLID (F_GETFL));
|
||||
if (curf < 0) return;
|
||||
if (v) curf |= O_NONBLOCK;
|
||||
else curf &= ~O_NONBLOCK;
|
||||
fcntl (FCNTLID (F_SETFL), curf);
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// fstream.h
|
||||
//
|
||||
|
||||
#ifndef FSTREAM_H_056E10F70EAD416443E3B36A2D6B5FA3
|
||||
#define FSTREAM_H_056E10F70EAD416443E3B36A2D6B5FA3
|
||||
|
||||
#include "uios.h"
|
||||
#include "ustring.h"
|
||||
|
||||
struct stat;
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// \class fstream fstream.h ustl.h
|
||||
///
|
||||
/// \brief Implements file operations.
|
||||
///
|
||||
/// This is not implemented as a stream, but rather as a base for one. You
|
||||
/// should use ifstream or ofstream if you want flow operators. Otherwise
|
||||
/// this only implements functions for binary i/o.
|
||||
///
|
||||
class fstream : public ios_base {
|
||||
public:
|
||||
fstream (void);
|
||||
explicit fstream (const char* filename, openmode mode = in | out);
|
||||
explicit fstream (int nfd, const char* filename = string::empty_string);
|
||||
~fstream (void) throw();
|
||||
void open (const char* filename, openmode mode, mode_t perms = 0644);
|
||||
void attach (int nfd, const char* filename = string::empty_string);
|
||||
void detach (void);
|
||||
void close (void);
|
||||
void sync (void);
|
||||
off_t read (void* p, off_t n);
|
||||
off_t readsome (void* p, off_t n);
|
||||
off_t write (const void* p, off_t n);
|
||||
off_t size (void) const;
|
||||
off_t seek (off_t n, seekdir whence = beg);
|
||||
off_t pos (void) const;
|
||||
void stat (struct stat& rs) const;
|
||||
int ioctl (const char* rname, int request, long argument = 0);
|
||||
inline int ioctl (const char* rname, int request, int argument) { return (fstream::ioctl (rname, request, long(argument))); }
|
||||
inline int ioctl (const char* rname, int request, void* argument) { return (fstream::ioctl (rname, request, intptr_t(argument))); }
|
||||
int fcntl (const char* rname, int request, long argument = 0);
|
||||
inline int fcntl (const char* rname, int request, int argument) { return (fstream::fcntl (rname, request, long(argument))); }
|
||||
inline int fcntl (const char* rname, int request, void* argument) { return (fstream::fcntl (rname, request, intptr_t(argument))); }
|
||||
memlink mmap (off_t n, off_t offset = 0);
|
||||
void munmap (memlink& l);
|
||||
void msync (memlink& l);
|
||||
void set_nonblock (bool v = true);
|
||||
inline int fd (void) const { return (m_fd); }
|
||||
inline bool is_open (void) const { return (fd() >= 0); }
|
||||
inline off_t tellg (void) const { return (pos()); }
|
||||
inline off_t tellp (void) const { return (pos()); }
|
||||
inline void seekg (off_t n, seekdir whence = beg) { seek (n, whence); }
|
||||
inline void seekp (off_t n, seekdir whence = beg) { seek (n, whence); }
|
||||
inline void flush (void) { sync(); }
|
||||
inline const string& name (void) const { return (m_Filename); }
|
||||
private:
|
||||
DLL_LOCAL static int om_to_flags (openmode m);
|
||||
DLL_LOCAL void set_and_throw (iostate s, const char* op);
|
||||
private:
|
||||
int m_fd; ///< Currently open file descriptor.
|
||||
string m_Filename; ///< Currently open filename.
|
||||
};
|
||||
|
||||
/// Argument macro for fstream::ioctl. Use like fs.ioctl (IOCTLID (TCGETS), &ts).
|
||||
#define IOCTLID(r) "ioctl("#r")", r
|
||||
#define FCNTLID(r) "fcntl("#r")", r
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,216 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// memblock.cc
|
||||
//
|
||||
// Allocated memory block.
|
||||
//
|
||||
|
||||
#include "fstream.h"
|
||||
#include "mistream.h"
|
||||
#include "memblock.h"
|
||||
#include "ualgo.h"
|
||||
#include "uassert.h"
|
||||
#include "umemory.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// Allocates 0 bytes for the internal block.
|
||||
memblock::memblock (void)
|
||||
: memlink (),
|
||||
m_Capacity (0)
|
||||
{
|
||||
}
|
||||
|
||||
/// Allocates \p n bytes for the internal block.
|
||||
memblock::memblock (size_type n)
|
||||
: memlink (),
|
||||
m_Capacity (0)
|
||||
{
|
||||
resize (n);
|
||||
}
|
||||
|
||||
/// links to \p p, \p n. Data can not be modified and will not be freed.
|
||||
memblock::memblock (const void* p, size_type n)
|
||||
: memlink (),
|
||||
m_Capacity (0)
|
||||
{
|
||||
assign (p, n);
|
||||
}
|
||||
|
||||
/// Links to what \p b is linked to.
|
||||
memblock::memblock (const cmemlink& b)
|
||||
: memlink (),
|
||||
m_Capacity (0)
|
||||
{
|
||||
assign (b);
|
||||
}
|
||||
|
||||
/// Links to what \p b is linked to.
|
||||
memblock::memblock (const memlink& b)
|
||||
: memlink (),
|
||||
m_Capacity (0)
|
||||
{
|
||||
assign (b);
|
||||
}
|
||||
|
||||
/// Links to what \p b is linked to.
|
||||
memblock::memblock (const memblock& b)
|
||||
: memlink (),
|
||||
m_Capacity (0)
|
||||
{
|
||||
assign (b);
|
||||
}
|
||||
|
||||
/// Frees internal data, if appropriate
|
||||
/// Only if the block was allocated using resize, or linked to using Manage,
|
||||
/// will it be freed. Also, Derived classes should call DestructBlock from
|
||||
/// their destructor, because upstream virtual functions are unavailable at
|
||||
/// this point and will not be called automatically.
|
||||
///
|
||||
memblock::~memblock (void)
|
||||
{
|
||||
if (!is_linked())
|
||||
deallocate();
|
||||
}
|
||||
|
||||
/// resizes the block to \p newSize bytes, reallocating if necessary.
|
||||
void memblock::resize (size_type newSize, bool bExact)
|
||||
{
|
||||
if (m_Capacity < newSize + minimumFreeCapacity())
|
||||
reserve (newSize, bExact);
|
||||
memlink::resize (newSize);
|
||||
}
|
||||
|
||||
/// Frees internal data.
|
||||
void memblock::deallocate (void) throw()
|
||||
{
|
||||
if (m_Capacity) {
|
||||
assert (cdata() && "Internal error: space allocated, but the pointer is NULL");
|
||||
assert (data() && "Internal error: read-only block is marked as allocated space");
|
||||
free (data());
|
||||
}
|
||||
unlink();
|
||||
}
|
||||
|
||||
/// Assumes control of the memory block \p p of size \p n.
|
||||
/// The block assigned using this function will be freed in the destructor.
|
||||
void memblock::manage (void* p, size_type n)
|
||||
{
|
||||
assert (p || !n);
|
||||
assert (!m_Capacity && "Already managing something. deallocate or unlink first.");
|
||||
link (p, n);
|
||||
m_Capacity = n;
|
||||
}
|
||||
|
||||
/// "Instantiate" a linked block by allocating and copying the linked data.
|
||||
void memblock::copy_link (void)
|
||||
{
|
||||
const cmemlink l (*this);
|
||||
if (is_linked())
|
||||
unlink();
|
||||
assign (l);
|
||||
}
|
||||
|
||||
/// Copies data from \p p, \p n.
|
||||
void memblock::assign (const void* p, size_type n)
|
||||
{
|
||||
assert ((p != (const void*) cdata() || size() == n) && "Self-assignment can not resize");
|
||||
resize (n);
|
||||
copy (p, n);
|
||||
}
|
||||
|
||||
/// \brief Reallocates internal block to hold at least \p newSize bytes.
|
||||
///
|
||||
/// Additional memory may be allocated, but for efficiency it is a very
|
||||
/// good idea to call reserve before doing byte-by-byte edit operations.
|
||||
/// The block size as returned by size() is not altered. reserve will not
|
||||
/// reduce allocated memory. If you think you are wasting space, call
|
||||
/// deallocate and start over. To avoid wasting space, use the block for
|
||||
/// only one purpose, and try to get that purpose to use similar amounts
|
||||
/// of memory on each iteration.
|
||||
///
|
||||
void memblock::reserve (size_type newSize, bool bExact)
|
||||
{
|
||||
if ((newSize += minimumFreeCapacity()) <= m_Capacity)
|
||||
return;
|
||||
void* oldBlock (is_linked() ? NULL : data());
|
||||
if (!bExact)
|
||||
newSize = Align (newSize, c_PageSize);
|
||||
pointer newBlock = (pointer) realloc (oldBlock, newSize);
|
||||
if (!newBlock)
|
||||
#if PLATFORM_ANDROID
|
||||
printf("bad_alloc\n");
|
||||
#else
|
||||
throw bad_alloc (newSize);
|
||||
#endif
|
||||
if (!oldBlock && cdata())
|
||||
copy_n (cdata(), min (size() + 1, newSize), newBlock);
|
||||
link (newBlock, size());
|
||||
m_Capacity = newSize;
|
||||
}
|
||||
|
||||
/// Swaps the contents with \p l
|
||||
void memblock::swap (memblock& l)
|
||||
{
|
||||
memlink::swap (l);
|
||||
::ustl::swap (m_Capacity, l.m_Capacity);
|
||||
}
|
||||
|
||||
/// Shifts the data in the linked block from \p start to \p start + \p n.
|
||||
memblock::iterator memblock::insert (iterator start, size_type n)
|
||||
{
|
||||
const uoff_t ip = start - begin();
|
||||
assert (ip <= size());
|
||||
resize (size() + n, false);
|
||||
memlink::insert (iat(ip), n);
|
||||
return (iat (ip));
|
||||
}
|
||||
|
||||
/// Shifts the data in the linked block from \p start + \p n to \p start.
|
||||
memblock::iterator memblock::erase (iterator start, size_type n)
|
||||
{
|
||||
const uoff_t ep = start - begin();
|
||||
assert (ep + n <= size());
|
||||
memlink::erase (start, n);
|
||||
memlink::resize (size() - n);
|
||||
return (iat (ep));
|
||||
}
|
||||
|
||||
/// Unlinks object.
|
||||
void memblock::unlink (void)
|
||||
{
|
||||
memlink::unlink();
|
||||
m_Capacity = 0;
|
||||
}
|
||||
|
||||
/// Reads the object from stream \p s
|
||||
void memblock::read (istream& is)
|
||||
{
|
||||
written_size_type n;
|
||||
is >> n;
|
||||
is.verify_remaining ("read", "ustl::memblock", n);
|
||||
resize (n);
|
||||
is.read (data(), writable_size());
|
||||
is.align (alignof (n));
|
||||
}
|
||||
|
||||
/// Reads the entire file \p "filename".
|
||||
void memblock::read_file (const char* filename)
|
||||
{
|
||||
fstream f;
|
||||
f.exceptions (fstream::allbadbits);
|
||||
f.open (filename, fstream::in);
|
||||
const off_t fsize (f.size());
|
||||
reserve (fsize);
|
||||
f.read (data(), fsize);
|
||||
f.close();
|
||||
resize (fsize);
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// memblock.h
|
||||
//
|
||||
|
||||
#ifndef MEMBLOCK_H_7ED63A891164CC43578E63664D52A196
|
||||
#define MEMBLOCK_H_7ED63A891164CC43578E63664D52A196
|
||||
|
||||
#include "memlink.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// \class memblock memblock.h ustl.h
|
||||
/// \ingroup MemoryManagement
|
||||
///
|
||||
/// \brief Allocated memory block.
|
||||
///
|
||||
/// Adds memory management capabilities to memlink. Uses malloc and realloc to
|
||||
/// maintain the internal pointer, but only if allocated using members of this class,
|
||||
/// or if linked to using the Manage() member function. Managed memory is automatically
|
||||
/// freed in the destructor.
|
||||
///
|
||||
class memblock : public memlink {
|
||||
public:
|
||||
static const size_type c_PageSize = 64; ///< The default minimum allocation unit.
|
||||
public:
|
||||
memblock (void);
|
||||
memblock (const void* p, size_type n);
|
||||
explicit memblock (size_type n);
|
||||
explicit memblock (const cmemlink& b);
|
||||
explicit memblock (const memlink& b);
|
||||
memblock (const memblock& b);
|
||||
virtual ~memblock (void);
|
||||
virtual void unlink (void);
|
||||
inline void assign (const cmemlink& l) { assign (l.cdata(), l.readable_size()); }
|
||||
inline const memblock& operator= (const cmemlink& l) { assign (l); return (*this); }
|
||||
inline const memblock& operator= (const memlink& l) { assign (l); return (*this); }
|
||||
inline const memblock& operator= (const memblock& l) { assign (l); return (*this); }
|
||||
void assign (const void* p, size_type n);
|
||||
void swap (memblock& l);
|
||||
void reserve (size_type newSize, bool bExact = true);
|
||||
void resize (size_type newSize, bool bExact = true);
|
||||
iterator insert (iterator start, size_type size);
|
||||
iterator erase (iterator start, size_type size);
|
||||
inline void clear (void) { resize (0); }
|
||||
inline bool is_linked (void) const { return (!m_Capacity && cdata()); }
|
||||
inline size_type max_size (void) const { return (is_linked() ? memlink::max_size() : SIZE_MAX); }
|
||||
inline size_type capacity (void) const { return (m_Capacity); }
|
||||
inline void manage (memlink& l) { manage (l.begin(), l.size()); }
|
||||
void deallocate (void) throw();
|
||||
void manage (void* p, size_type n);
|
||||
void copy_link (void);
|
||||
void read (istream& is);
|
||||
void read_file (const char* filename);
|
||||
protected:
|
||||
inline virtual size_type minimumFreeCapacity (void) const { return (0); }
|
||||
private:
|
||||
size_type m_Capacity; ///< Number of bytes allocated by Resize.
|
||||
};
|
||||
|
||||
/// Reads object \p l from stream \p is
|
||||
inline istream& operator>> (istream& is, memblock& l)
|
||||
{
|
||||
l.read (is);
|
||||
return (is);
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// memlink.cc
|
||||
//
|
||||
// A pointer to a sized block of memory.
|
||||
//
|
||||
|
||||
#include "mistream.h"
|
||||
#include "uassert.h"
|
||||
#include "ustdxept.h"
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// Reads the object from stream \p s
|
||||
void memlink::read (istream& is)
|
||||
{
|
||||
written_size_type n;
|
||||
is >> n;
|
||||
is.verify_remaining ("read", "ustl::memlink", n);
|
||||
if (n > size())
|
||||
#if PLATFORM_ANDROID
|
||||
printf("length error\n");
|
||||
#else
|
||||
throw length_error ("memlink can not increase the size of the linked storage for reading");
|
||||
#endif
|
||||
resize (n);
|
||||
is.read (data(), n);
|
||||
is.align (alignof (n));
|
||||
}
|
||||
|
||||
/// Copies data from \p p, \p n to the linked block starting at \p start.
|
||||
void memlink::copy (iterator start, const void* p, size_type n)
|
||||
{
|
||||
assert (data() || !n);
|
||||
assert (p || !n);
|
||||
assert (start >= begin() && start + n <= end());
|
||||
if (p)
|
||||
copy_n (const_iterator(p), n, start);
|
||||
}
|
||||
|
||||
/// Fills the linked block with the given pattern.
|
||||
/// \arg start Offset at which to start filling the linked block
|
||||
/// \arg p Pointer to the pattern.
|
||||
/// \arg elSize Size of the pattern.
|
||||
/// \arg elCount Number of times to write the pattern.
|
||||
/// Total number of bytes written is \p elSize * \p elCount.
|
||||
///
|
||||
void memlink::fill (iterator start, const void* p, size_type elSize, size_type elCount)
|
||||
{
|
||||
assert (data() || !elCount || !elSize);
|
||||
assert (start >= begin() && start + elSize * elCount <= end());
|
||||
if (elSize == 1)
|
||||
fill_n (start, elCount, *reinterpret_cast<const uint8_t*>(p));
|
||||
else while (elCount--)
|
||||
start = copy_n (const_iterator(p), elSize, start);
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// memlink.h
|
||||
|
||||
#ifndef MEMLINK_H_798D25827C8E322D2D7E734B169FF5FC
|
||||
#define MEMLINK_H_798D25827C8E322D2D7E734B169FF5FC
|
||||
|
||||
#include "cmemlink.h"
|
||||
#include "ualgo.h"
|
||||
#include "uassert.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// \class memlink memlink.h ustl.h
|
||||
/// \ingroup MemoryManagement
|
||||
///
|
||||
/// \brief Wrapper for pointer to block with size.
|
||||
///
|
||||
/// Use this class the way you would a pointer to an allocated unstructured block.
|
||||
/// The pointer and block size are available through member functions and cast operator.
|
||||
///
|
||||
/// Example usage:
|
||||
/// \code
|
||||
/// void* p = malloc (46721);
|
||||
/// memlink a, b;
|
||||
/// a.link (p, 46721);
|
||||
/// assert (a.size() == 46721));
|
||||
/// b = a;
|
||||
/// assert (b.size() == 46721));
|
||||
/// assert (b.begin() + 34 == a.begin + 34);
|
||||
/// assert (0 == memcmp (a, b, 12));
|
||||
/// a.fill (673, b, 42, 67);
|
||||
/// b.erase (87, 12);
|
||||
/// \endcode
|
||||
///
|
||||
class memlink : public cmemlink {
|
||||
public:
|
||||
typedef value_type* pointer;
|
||||
typedef cmemlink::pointer const_pointer;
|
||||
typedef cmemlink::const_iterator const_iterator;
|
||||
typedef pointer iterator;
|
||||
typedef const memlink& rcself_t;
|
||||
public:
|
||||
inline memlink (void) : cmemlink() {}
|
||||
inline memlink (void* p, size_type n) : cmemlink (p, n) {}
|
||||
inline memlink (const void* p, size_type n) : cmemlink (p, n) {}
|
||||
inline memlink (rcself_t l) : cmemlink (l) {}
|
||||
inline explicit memlink (const cmemlink& l) : cmemlink (l) {}
|
||||
inline pointer data (void) { return (const_cast<pointer>(cdata())); }
|
||||
inline iterator begin (void) { return (iterator (data())); }
|
||||
inline iterator iat (size_type i) { assert (i <= size()); return (begin() + i); }
|
||||
inline iterator end (void) { return (iat (size())); }
|
||||
inline const_iterator begin (void) const { return (cmemlink::begin()); }
|
||||
inline const_iterator end (void) const { return (cmemlink::end()); }
|
||||
inline const_iterator iat (size_type i) const { return (cmemlink::iat (i)); }
|
||||
size_type writable_size (void) const { return (size()); }
|
||||
inline rcself_t operator= (const cmemlink& l) { cmemlink::operator= (l); return (*this); }
|
||||
inline rcself_t operator= (rcself_t l) { cmemlink::operator= (l); return (*this); }
|
||||
inline void link (const void* p, size_type n) { cmemlink::link (p, n); }
|
||||
inline void link (void* p, size_type n) { cmemlink::link (p, n); }
|
||||
inline void link (const cmemlink& l) { cmemlink::link (l); }
|
||||
inline void link (memlink& l) { cmemlink::link (l); }
|
||||
OVERLOAD_POINTER_AND_SIZE_T_V2(link, void*)
|
||||
OVERLOAD_POINTER_AND_SIZE_T_V2(link, const void*)
|
||||
inline void link (const void* first, const void* last) { link (first, distance (first, last)); }
|
||||
inline void link (void* first, void* last) { link (first, distance (first, last)); }
|
||||
inline void relink (const void* p, size_type n) { cmemlink::relink (p, n); }
|
||||
inline void relink (void* p, size_type n) { cmemlink::relink (p, n); }
|
||||
inline void copy (const cmemlink& l) { copy (begin(), l.cdata(), l.size()); }
|
||||
inline void copy (const void* p, size_type n) { copy (begin(), p, n); }
|
||||
void copy (iterator offset, const void* p, size_type n);
|
||||
inline void swap (memlink& l) { cmemlink::swap (l); }
|
||||
void fill (iterator start, const void* p, size_type elsize, size_type elCount = 1);
|
||||
inline void insert (iterator start, size_type size);
|
||||
inline void erase (iterator start, size_type size);
|
||||
void read (istream& is);
|
||||
};
|
||||
|
||||
/// Shifts the data in the linked block from \p start to \p start + \p n.
|
||||
/// The contents of the uncovered bytes is undefined.
|
||||
inline void memlink::insert (iterator start, size_type n)
|
||||
{
|
||||
assert (data() || !n);
|
||||
assert (cmemlink::begin() || !n);
|
||||
assert (start >= begin() && start + n <= end());
|
||||
rotate (start, end() - n, end());
|
||||
}
|
||||
|
||||
/// Shifts the data in the linked block from \p start + \p n to \p start.
|
||||
/// The contents of the uncovered bytes is undefined.
|
||||
inline void memlink::erase (iterator start, size_type n)
|
||||
{
|
||||
assert (data() || !n);
|
||||
assert (cmemlink::begin() || !n);
|
||||
assert (start >= begin() && start + n <= end());
|
||||
rotate (start, start + n, end());
|
||||
}
|
||||
|
||||
/// Reads object \p l from stream \p is
|
||||
inline istream& operator>> (istream& is, memlink& l)
|
||||
{
|
||||
l.read (is);
|
||||
return (is);
|
||||
}
|
||||
|
||||
/// Use with memlink-derived classes to allocate and link to stack space.
|
||||
#define alloca_link(m,n) (m).link (alloca (n), (n))
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,242 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// mstream.cpp
|
||||
//
|
||||
// Helper classes to read and write packed binary streams.
|
||||
//
|
||||
|
||||
#include "mistream.h"
|
||||
#include "sostream.h"
|
||||
#include "ualgo.h"
|
||||
#include "uassert.h"
|
||||
#include "ustring.h"
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
namespace ustl {
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/// \brief Constructs a stream attached to nothing.
|
||||
/// A stream attached to nothing is not usable. Call Link() functions
|
||||
/// inherited from cmemlink to attach to some memory block.
|
||||
///
|
||||
istream::istream (void)
|
||||
: cmemlink (),
|
||||
m_Pos (0)
|
||||
{
|
||||
}
|
||||
|
||||
/// Attaches the stream to a block at \p p of size \p n.
|
||||
istream::istream (const void* p, size_type n)
|
||||
: cmemlink (p, n),
|
||||
m_Pos (0)
|
||||
{
|
||||
}
|
||||
|
||||
/// Attaches to the block pointed to by \p source.
|
||||
istream::istream (const cmemlink& source)
|
||||
: cmemlink (source),
|
||||
m_Pos (0)
|
||||
{
|
||||
}
|
||||
|
||||
/// Attaches to the block pointed to by source of size source.pos()
|
||||
istream::istream (const ostream& source)
|
||||
: cmemlink (source.begin(), source.pos()),
|
||||
m_Pos (0)
|
||||
{
|
||||
}
|
||||
|
||||
/// Swaps contents with \p is
|
||||
void istream::swap (istream& is)
|
||||
{
|
||||
cmemlink::swap (is);
|
||||
::ustl::swap (m_Pos, is.m_Pos);
|
||||
}
|
||||
|
||||
/// Checks that \p n bytes are available in the stream, or else throws.
|
||||
void istream::verify_remaining (const char* op, const char* type, size_t n) const
|
||||
{
|
||||
if (remaining() < n)
|
||||
#if PLATFORM_ANDROID
|
||||
printf("stream bounds exception\n");
|
||||
#else
|
||||
throw stream_bounds_exception (op, type, pos(), n, remaining());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Reads \p n bytes into \p buffer.
|
||||
void istream::read (void* buffer, size_type n)
|
||||
{
|
||||
#ifdef WANT_STREAM_BOUNDS_CHECKING
|
||||
verify_remaining ("read", "binary data", n);
|
||||
#else
|
||||
assert (remaining() >= n && "Reading past end of buffer. Make sure you are reading the right format.");
|
||||
#endif
|
||||
copy_n (ipos(), n, reinterpret_cast<value_type*>(buffer));
|
||||
m_Pos += n;
|
||||
}
|
||||
|
||||
/// Reads a null-terminated string into \p str.
|
||||
void istream::read_strz (string& str)
|
||||
{
|
||||
const_iterator zp = find (ipos(), end(), string::c_Terminator);
|
||||
if (zp == end())
|
||||
zp = ipos();
|
||||
const size_type strl = distance (ipos(), zp);
|
||||
str.resize (strl);
|
||||
copy (ipos(), zp, str.begin());
|
||||
m_Pos += strl + 1;
|
||||
}
|
||||
|
||||
/// Reads at most \p n bytes into \p s.
|
||||
istream::size_type istream::readsome (void* s, size_type n)
|
||||
{
|
||||
if (remaining() < n)
|
||||
underflow (n);
|
||||
const size_type ntr (min (n, remaining()));
|
||||
read (s, ntr);
|
||||
return (ntr);
|
||||
}
|
||||
|
||||
/// Writes all unread bytes into \p os.
|
||||
void istream::write (ostream& os) const
|
||||
{
|
||||
os.write (ipos(), remaining());
|
||||
}
|
||||
|
||||
/// Writes the object to stream \p os.
|
||||
void istream::text_write (ostringstream& os) const
|
||||
{
|
||||
os.write (ipos(), remaining());
|
||||
}
|
||||
|
||||
/// Links to \p p of size \p n
|
||||
void istream::unlink (void)
|
||||
{
|
||||
cmemlink::unlink();
|
||||
m_Pos = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/// \brief Constructs a stream attached to nothing.
|
||||
/// A stream attached to nothing is not usable. Call Link() functions
|
||||
/// inherited from memlink to attach to some memory block.
|
||||
///
|
||||
ostream::ostream (void)
|
||||
: memlink (),
|
||||
m_Pos (0)
|
||||
{
|
||||
}
|
||||
|
||||
/// Attaches the stream to a block at \p p of size \p n.
|
||||
ostream::ostream (void* p, size_type n)
|
||||
: memlink (p, n),
|
||||
m_Pos (0)
|
||||
{
|
||||
}
|
||||
|
||||
/// Attaches to the block pointed to by \p source.
|
||||
ostream::ostream (const memlink& source)
|
||||
: memlink (source),
|
||||
m_Pos (0)
|
||||
{
|
||||
}
|
||||
|
||||
/// Links to \p p of size \p n
|
||||
void ostream::unlink (void)
|
||||
{
|
||||
memlink::unlink();
|
||||
m_Pos = 0;
|
||||
}
|
||||
|
||||
/// Checks that \p n bytes are available in the stream, or else throws.
|
||||
void ostream::verify_remaining (const char* op, const char* type, size_t n) const
|
||||
{
|
||||
if (remaining() < n)
|
||||
#if PLATFORM_ANDROID
|
||||
printf("stream bounds exception\n");
|
||||
#else
|
||||
throw stream_bounds_exception (op, type, pos(), n, remaining());
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Aligns the write pointer on \p grain. The skipped bytes are zeroed.
|
||||
void ostream::align (size_type grain)
|
||||
{
|
||||
const size_t r = pos() % grain;
|
||||
size_t nb = grain - r;
|
||||
if (!r) nb = 0;
|
||||
#ifdef WANT_STREAM_BOUNDS_CHECKING
|
||||
verify_remaining ("align", "padding", nb);
|
||||
#else
|
||||
assert (remaining() >= nb && "Buffer overrun. Check your stream size calculations.");
|
||||
#endif
|
||||
fill_n (ipos(), nb, '\x0');
|
||||
m_Pos += nb;
|
||||
}
|
||||
|
||||
/// Writes \p n bytes from \p buffer.
|
||||
void ostream::write (const void* buffer, size_type n)
|
||||
{
|
||||
#ifdef WANT_STREAM_BOUNDS_CHECKING
|
||||
verify_remaining ("write", "binary data", n);
|
||||
#else
|
||||
assert (remaining() >= n && "Buffer overrun. Check your stream size calculations.");
|
||||
#endif
|
||||
copy_n (const_iterator(buffer), n, ipos());
|
||||
m_Pos += n;
|
||||
}
|
||||
|
||||
/// Writes \p str as a null-terminated string.
|
||||
void ostream::write_strz (const char* str)
|
||||
{
|
||||
write (str, strlen(str));
|
||||
iwrite (string::c_Terminator);
|
||||
}
|
||||
|
||||
/// Writes all available data from \p is.
|
||||
void ostream::read (istream& is)
|
||||
{
|
||||
is.write (*this);
|
||||
is.seek (is.size());
|
||||
}
|
||||
|
||||
/// Writes all written data to \p os.
|
||||
void ostream::text_write (ostringstream& os) const
|
||||
{
|
||||
os.write (begin(), pos());
|
||||
}
|
||||
|
||||
/// Inserts an empty area of \p size, at \p start.
|
||||
void ostream::insert (iterator start, size_type s)
|
||||
{
|
||||
memlink::insert (start, s);
|
||||
m_Pos += s;
|
||||
}
|
||||
|
||||
/// Erases an area of \p size, at \p start.
|
||||
void ostream::erase (iterator start, size_type s)
|
||||
{
|
||||
m_Pos -= s;
|
||||
memlink::erase (start, s);
|
||||
}
|
||||
|
||||
/// Swaps with \p os
|
||||
void ostream::swap (ostream& os)
|
||||
{
|
||||
memlink::swap (os);
|
||||
::ustl::swap (m_Pos, os.m_Pos);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
@@ -1,293 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// mistream.h
|
||||
//
|
||||
#ifndef MISTREAM_H_103AEF1F266C04AA1A817D38705983DA
|
||||
#define MISTREAM_H_103AEF1F266C04AA1A817D38705983DA
|
||||
|
||||
#include "memlink.h"
|
||||
#include "uexception.h"
|
||||
#include "strmsize.h"
|
||||
#include "uassert.h"
|
||||
#include "utf8.h"
|
||||
#include "uios.h"
|
||||
#ifdef WANT_STREAM_BOUNDS_CHECKING
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
|
||||
namespace ustl {
|
||||
|
||||
class ostream;
|
||||
class memlink;
|
||||
class string;
|
||||
|
||||
/// \class istream mistream.h ustl.h
|
||||
/// \ingroup BinaryStreams
|
||||
///
|
||||
/// \brief Helper class to read packed binary streams.
|
||||
///
|
||||
/// This class contains a set of functions to read integral types from an
|
||||
/// unstructured memory block. Unpacking binary file data can be done this
|
||||
/// way, for instance. aligning the data is your responsibility, and can
|
||||
/// be accomplished by proper ordering of reads and by calling the align()
|
||||
/// function. Unaligned access is usually slower by orders of magnitude and,
|
||||
/// on some architectures, such as PowerPC, can cause your program to crash.
|
||||
/// Therefore, all read functions have asserts to check alignment.
|
||||
/// Overreading the end of the stream will also cause a crash (an assert in
|
||||
/// debug builds). Oh, and don't be intimidated by the size of the inlines
|
||||
/// here. In the assembly code the compiler will usually chop everything down
|
||||
/// to five instructions each.
|
||||
///
|
||||
/// Alignment rules for your objects:
|
||||
/// - Assume your writes start off 4-byte aligned.
|
||||
/// - After completion, \ref istream::align the stream to at least 4.
|
||||
/// - If data portability between 32bit and 64bit platforms is important
|
||||
/// (it often is not, in config files and the like), ensure you are always
|
||||
/// using fixed-size types and are aligning to a fixed grain. Avoid writing
|
||||
/// 8-byte types, and if you do, manually align before doing so.
|
||||
/// - Non-default alignment is allowed if you plan to frequently write this
|
||||
/// object in array form and alignment would be costly. For example, an
|
||||
/// array of uint16_t-sized objects may leave the stream uint16_t aligned
|
||||
/// as long as you know about it and will default-align the stream after
|
||||
/// writing the array (note: \ref vector will already do this for you)
|
||||
///
|
||||
/// Example code:
|
||||
/// \code
|
||||
/// memblock b;
|
||||
/// b.read_file ("test.file");
|
||||
/// ostream is (b);
|
||||
/// is >> boolVar >> ios::talign<int>();
|
||||
/// is >> intVar >> floatVar;
|
||||
/// is.read (binaryData, binaryDataSize);
|
||||
/// is.align();
|
||||
/// \endcode
|
||||
///
|
||||
class istream : public cmemlink, public ios_base {
|
||||
public:
|
||||
istream (void);
|
||||
istream (const void* p, size_type n);
|
||||
explicit istream (const cmemlink& source);
|
||||
explicit istream (const ostream& source);
|
||||
inline iterator end (void) const { return (cmemlink::end()); }
|
||||
inline void link (const void* p, size_type n) { cmemlink::link (p, n); }
|
||||
inline void link (const cmemlink& l) { cmemlink::link (l.cdata(), l.readable_size()); }
|
||||
inline void link (const void* f, const void* l) { cmemlink::link (f, l); }
|
||||
OVERLOAD_POINTER_AND_SIZE_T_V2(link, const void*)
|
||||
inline void relink (const void* p, size_type n) { cmemlink::relink (p, n); m_Pos = 0; }
|
||||
inline void relink (const cmemlink& l) { relink (l.cdata(), l.readable_size()); }
|
||||
virtual void unlink (void);
|
||||
inline virtual size_type underflow (size_type = 1) { return (remaining()); }
|
||||
inline uoff_t pos (void) const { return (m_Pos); }
|
||||
inline const_iterator ipos (void) const { return (begin() + pos()); }
|
||||
inline size_type remaining (void) const { return (size() - pos()); }
|
||||
inline void seek (uoff_t newPos);
|
||||
inline void iseek (const_iterator newPos);
|
||||
inline void skip (size_type nBytes);
|
||||
inline bool aligned (size_type grain = c_DefaultAlignment) const;
|
||||
void verify_remaining (const char* op, const char* type, size_t n) const;
|
||||
inline size_type align_size (size_type grain = c_DefaultAlignment) const;
|
||||
inline void align (size_type grain = c_DefaultAlignment);
|
||||
void swap (istream& is);
|
||||
void read (void* buffer, size_type size);
|
||||
inline void read (memlink& buf) { read (buf.begin(), buf.writable_size()); }
|
||||
void read_strz (string& str);
|
||||
size_type readsome (void* s, size_type n);
|
||||
inline void read (istream&) { }
|
||||
void write (ostream& os) const;
|
||||
void text_write (ostringstream& os) const;
|
||||
inline size_t stream_size (void) const { return (remaining()); }
|
||||
template <typename T>
|
||||
inline void iread (T& v);
|
||||
inline void ungetc (void) { seek (pos() - 1); }
|
||||
inline off_t tellg (void) const { return (pos()); }
|
||||
inline void seekg (off_t p, seekdir d = beg);
|
||||
private:
|
||||
uoff_t m_Pos; ///< The current read position.
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
template <typename T, typename Stream>
|
||||
inline size_t required_stream_size (T, const Stream&) { return (1); }
|
||||
template <typename T>
|
||||
inline size_t required_stream_size (T v, const istream&) { return (stream_size_of(v)); }
|
||||
|
||||
template <typename Stream>
|
||||
inline bool stream_at_eof (const Stream& stm) { return (stm.eof()); }
|
||||
template <>
|
||||
inline bool stream_at_eof (const istream&) { return (false); }
|
||||
|
||||
/// \class istream_iterator
|
||||
/// \ingroup BinaryStreamIterators
|
||||
///
|
||||
/// \brief An iterator over an istream to use with uSTL algorithms.
|
||||
///
|
||||
template <typename T, typename Stream = istream>
|
||||
class istream_iterator {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef const value_type* pointer;
|
||||
typedef const value_type& reference;
|
||||
typedef size_t size_type;
|
||||
public:
|
||||
istream_iterator (void) : m_pis (NULL), m_v() {}
|
||||
explicit istream_iterator (Stream& is) : m_pis (&is), m_v() { Read(); }
|
||||
istream_iterator (const istream_iterator& i) : m_pis (i.m_pis), m_v (i.m_v) {}
|
||||
/// Reads and returns the next value.
|
||||
inline const T& operator* (void) { return (m_v); }
|
||||
inline istream_iterator& operator++ (void) { Read(); return (*this); }
|
||||
inline istream_iterator& operator-- (void) { m_pis->seek (m_pis->pos() - 2 * stream_size_of(m_v)); return (operator++()); }
|
||||
inline istream_iterator operator++ (int) { istream_iterator old (*this); operator++(); return (old); }
|
||||
inline istream_iterator operator-- (int) { istream_iterator old (*this); operator--(); return (old); }
|
||||
inline istream_iterator& operator+= (size_type n) { while (n--) operator++(); return (*this); }
|
||||
inline istream_iterator& operator-= (size_type n) { m_pis->seek (m_pis->pos() - (n + 1) * stream_size_of(m_v)); return (operator++()); }
|
||||
inline istream_iterator operator- (size_type n) const { istream_iterator result (*this); return (result -= n); }
|
||||
inline difference_type operator- (const istream_iterator& i) const { return (distance (i.m_pis->pos(), m_pis->pos()) / stream_size_of(m_v)); }
|
||||
inline bool operator== (const istream_iterator& i) const { return ((!m_pis && !i.m_pis) || (m_pis && i.m_pis && m_pis->pos() == i.m_pis->pos())); }
|
||||
inline bool operator< (const istream_iterator& i) const { return (!i.m_pis || (m_pis && m_pis->pos() < i.m_pis->pos())); }
|
||||
private:
|
||||
void Read (void)
|
||||
{
|
||||
if (!m_pis)
|
||||
return;
|
||||
const size_t rs (required_stream_size (m_v, *m_pis));
|
||||
if (m_pis->remaining() < rs && m_pis->underflow (rs) < rs) {
|
||||
m_pis = NULL;
|
||||
return;
|
||||
}
|
||||
*m_pis >> m_v;
|
||||
if (stream_at_eof (*m_pis))
|
||||
m_pis = NULL;
|
||||
}
|
||||
private:
|
||||
Stream* m_pis; ///< The host stream.
|
||||
T m_v; ///< Last read value; cached to be returnable as a const reference.
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// Sets the current read position to \p newPos
|
||||
inline void istream::seek (uoff_t newPos)
|
||||
{
|
||||
#ifdef WANT_STREAM_BOUNDS_CHECKING
|
||||
if (newPos > size())
|
||||
throw stream_bounds_exception ("seekg", "byte", pos(), newPos - pos(), size());
|
||||
#else
|
||||
assert (newPos <= size());
|
||||
#endif
|
||||
m_Pos = newPos;
|
||||
}
|
||||
|
||||
/// Sets the current read position to \p newPos
|
||||
inline void istream::iseek (const_iterator newPos)
|
||||
{
|
||||
seek (distance (begin(), newPos));
|
||||
}
|
||||
|
||||
/// Sets the current write position to \p p based on \p d.
|
||||
inline void istream::seekg (off_t p, seekdir d)
|
||||
{
|
||||
switch (d) {
|
||||
case beg: seek (p); break;
|
||||
case cur: seek (pos() + p); break;
|
||||
case ios_base::end: seek (size() - p); break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Skips \p nBytes without reading them.
|
||||
inline void istream::skip (size_type nBytes)
|
||||
{
|
||||
seek (pos() + nBytes);
|
||||
}
|
||||
|
||||
/// Returns the number of bytes to skip to be aligned on \p grain.
|
||||
inline istream::size_type istream::align_size (size_type grain) const
|
||||
{
|
||||
return (Align (pos(), grain) - pos());
|
||||
}
|
||||
|
||||
/// Returns \c true if the read position is aligned on \p grain
|
||||
inline bool istream::aligned (size_type grain) const
|
||||
{
|
||||
assert (uintptr_t(begin()) % grain == 0 && "Streams should be attached aligned at the maximum element grain to avoid bus errors.");
|
||||
return (pos() % grain == 0);
|
||||
}
|
||||
|
||||
/// aligns the read position on \p grain
|
||||
inline void istream::align (size_type grain)
|
||||
{
|
||||
seek (Align (pos(), grain));
|
||||
}
|
||||
|
||||
/// Reads type T from the stream via a direct pointer cast.
|
||||
template <typename T>
|
||||
inline void istream::iread (T& v)
|
||||
{
|
||||
assert (aligned (alignof (T())));
|
||||
#ifdef WANT_STREAM_BOUNDS_CHECKING
|
||||
verify_remaining ("read", typeid(v).name(), sizeof(T));
|
||||
#else
|
||||
assert (remaining() >= sizeof(T));
|
||||
#endif
|
||||
v = *reinterpret_cast<const T*>(ipos());
|
||||
m_Pos += sizeof(T);
|
||||
}
|
||||
|
||||
#define ISTREAM_OPERATOR(type) \
|
||||
inline istream& operator>> (istream& is, type& v) { is.iread(v); return (is); }
|
||||
|
||||
template <typename T>
|
||||
ISTREAM_OPERATOR(T*)
|
||||
ISTREAM_OPERATOR(int8_t)
|
||||
ISTREAM_OPERATOR(uint8_t)
|
||||
ISTREAM_OPERATOR(int16_t)
|
||||
ISTREAM_OPERATOR(uint16_t)
|
||||
ISTREAM_OPERATOR(int32_t)
|
||||
ISTREAM_OPERATOR(uint32_t)
|
||||
ISTREAM_OPERATOR(float)
|
||||
ISTREAM_OPERATOR(double)
|
||||
ISTREAM_OPERATOR(wchar_t)
|
||||
#if SIZE_OF_BOOL == SIZE_OF_CHAR
|
||||
ISTREAM_OPERATOR(bool)
|
||||
#else
|
||||
inline istream& operator>> (istream& is, bool& v)
|
||||
{ uint8_t v8; is.iread (v8); v = v8; return (is); }
|
||||
#endif
|
||||
#if HAVE_THREE_CHAR_TYPES
|
||||
ISTREAM_OPERATOR(char)
|
||||
#endif
|
||||
#if HAVE_INT64_T
|
||||
ISTREAM_OPERATOR(int64_t)
|
||||
ISTREAM_OPERATOR(uint64_t)
|
||||
#endif
|
||||
#if SIZE_OF_LONG == SIZE_OF_INT
|
||||
ISTREAM_OPERATOR(long)
|
||||
ISTREAM_OPERATOR(unsigned long)
|
||||
#endif
|
||||
#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
|
||||
ISTREAM_OPERATOR(long long)
|
||||
ISTREAM_OPERATOR(unsigned long long)
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
typedef istream_iterator<utf8subchar_t> istream_iterator_for_utf8;
|
||||
typedef utf8in_iterator<istream_iterator_for_utf8> utf8istream_iterator;
|
||||
|
||||
/// Returns a UTF-8 adaptor reading from \p is.
|
||||
inline utf8istream_iterator utf8in (istream& is)
|
||||
{
|
||||
istream_iterator_for_utf8 si (is);
|
||||
return (utf8istream_iterator (si));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,260 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// mostream.h
|
||||
|
||||
#ifndef MOSTREAM_H_24A8C5397E0848216573E5670930FC9A
|
||||
#define MOSTREAM_H_24A8C5397E0848216573E5670930FC9A
|
||||
|
||||
#include "memlink.h"
|
||||
#include "uassert.h"
|
||||
#include "uexception.h"
|
||||
#include "utf8.h"
|
||||
#include "uios.h"
|
||||
#include <typeinfo>
|
||||
|
||||
namespace ustl {
|
||||
|
||||
class istream;
|
||||
class string;
|
||||
|
||||
/// \class ostream mostream.h ustl.h
|
||||
/// \ingroup BinaryStreams
|
||||
///
|
||||
/// \brief Helper class to write packed binary streams.
|
||||
///
|
||||
/// This class contains a set of functions to write integral types into an
|
||||
/// unstructured memory block. Packing binary file data can be done this
|
||||
/// way, for instance. aligning the data is your responsibility, and can
|
||||
/// be accomplished by proper ordering of writes and by calling \ref ostream::align.
|
||||
/// Unaligned access is usually slower by orders of magnitude and,
|
||||
/// on some architectures, such as PowerPC, can cause your program to crash.
|
||||
/// Therefore, all write functions have asserts to check alignment.
|
||||
/// See \ref istream documentation for rules on designing your data format.
|
||||
/// Overwriting the end of the stream will also cause a crash (an assert in
|
||||
/// debug builds). Oh, and don't be intimidated by the size of the inlines
|
||||
/// here. In the assembly code the compiler will usually chop everything down
|
||||
/// to five instructions each.
|
||||
///
|
||||
/// Example code:
|
||||
/// \code
|
||||
/// memblock b;
|
||||
/// ostream os (b);
|
||||
/// os << boolVar << ios::talign<int>();
|
||||
/// os << intVar << floatVar;
|
||||
/// os.write (binaryData, binaryDataSize);
|
||||
/// os.align();
|
||||
/// b.resize (os.pos());
|
||||
/// b.write_file ("test.file");
|
||||
/// \endcode
|
||||
///
|
||||
class ostream : public memlink, public ios_base {
|
||||
public:
|
||||
ostream (void);
|
||||
ostream (void* p, size_type n);
|
||||
explicit ostream (const memlink& source);
|
||||
inline iterator end (void) { return (memlink::end()); }
|
||||
inline const_iterator end (void) const { return (memlink::end()); }
|
||||
inline void seek (uoff_t newPos);
|
||||
inline void iseek (const_iterator newPos);
|
||||
inline void skip (size_type nBytes);
|
||||
inline uoff_t pos (void) const { return (m_Pos); }
|
||||
inline iterator ipos (void) { return (begin() + pos()); }
|
||||
inline const_iterator ipos (void) const { return (begin() + pos()); }
|
||||
inline size_type remaining (void) const;
|
||||
inline bool aligned (size_type grain = c_DefaultAlignment) const;
|
||||
void verify_remaining (const char* op, const char* type, size_t n) const;
|
||||
inline size_type align_size (size_type grain = c_DefaultAlignment) const;
|
||||
void align (size_type grain = c_DefaultAlignment);
|
||||
void write (const void* buffer, size_type size);
|
||||
inline void write (const cmemlink& buf);
|
||||
void write_strz (const char* str);
|
||||
void read (istream& is);
|
||||
inline void write (ostream& os) const { os.write (begin(), pos()); }
|
||||
void text_write (ostringstream& os) const;
|
||||
inline size_t stream_size (void) const { return (pos()); }
|
||||
void insert (iterator start, size_type size);
|
||||
void erase (iterator start, size_type size);
|
||||
void swap (ostream& os);
|
||||
template <typename T>
|
||||
inline void iwrite (const T& v);
|
||||
inline virtual size_type overflow (size_type = 1){ return (remaining()); }
|
||||
virtual void unlink (void);
|
||||
inline void link (void* p, size_type n) { memlink::link (p, n); }
|
||||
inline void link (memlink& l) { memlink::link (l.data(), l.writable_size()); }
|
||||
inline void link (void* f, void* l) { memlink::link (f, l); }
|
||||
OVERLOAD_POINTER_AND_SIZE_T_V2(link, void*)
|
||||
inline void relink (void* p, size_type n) { memlink::relink (p, n); m_Pos = 0; }
|
||||
inline void relink (memlink& l) { relink (l.data(), l.writable_size()); }
|
||||
inline void seekp (off_t p, seekdir d = beg);
|
||||
inline off_t tellp (void) const { return (pos()); }
|
||||
protected:
|
||||
inline void SetPos (uoff_t newPos) { m_Pos = newPos; }
|
||||
private:
|
||||
uoff_t m_Pos; ///< Current write position.
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// \class ostream_iterator mostream.h ustl.h
|
||||
/// \ingroup BinaryStreamIterators
|
||||
///
|
||||
/// \brief An iterator over an ostream to use with uSTL algorithms.
|
||||
///
|
||||
template <typename T, typename Stream = ostream>
|
||||
class ostream_iterator {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
typedef ostream::size_type size_type;
|
||||
public:
|
||||
inline explicit ostream_iterator (Stream& os)
|
||||
: m_Os (os) {}
|
||||
inline ostream_iterator (const ostream_iterator& iter)
|
||||
: m_Os (iter.m_Os) {}
|
||||
/// Writes \p v into the stream.
|
||||
inline ostream_iterator& operator= (const T& v)
|
||||
{ m_Os << v; return (*this); }
|
||||
inline ostream_iterator& operator* (void) { return (*this); }
|
||||
inline ostream_iterator& operator++ (void) { return (*this); }
|
||||
inline ostream_iterator operator++ (int) { return (*this); }
|
||||
inline ostream_iterator& operator+= (size_type n) { m_Os.skip (n); return (*this); }
|
||||
inline bool operator== (const ostream_iterator& i) const
|
||||
{ return (m_Os.pos() == i.m_Os.pos()); }
|
||||
inline bool operator< (const ostream_iterator& i) const
|
||||
{ return (m_Os.pos() < i.m_Os.pos()); }
|
||||
private:
|
||||
Stream& m_Os;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
typedef ostream_iterator<utf8subchar_t> ostream_iterator_for_utf8;
|
||||
typedef utf8out_iterator<ostream_iterator_for_utf8> utf8ostream_iterator;
|
||||
|
||||
/// Returns a UTF-8 adaptor writing to \p os.
|
||||
inline utf8ostream_iterator utf8out (ostream& os)
|
||||
{
|
||||
ostream_iterator_for_utf8 si (os);
|
||||
return (utf8ostream_iterator (si));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// Move the write pointer to \p newPos
|
||||
inline void ostream::seek (uoff_t newPos)
|
||||
{
|
||||
#ifdef WANT_STREAM_BOUNDS_CHECKING
|
||||
if (newPos > size())
|
||||
throw stream_bounds_exception ("seekp", "byte", pos(), newPos - pos(), size());
|
||||
#else
|
||||
assert (newPos <= size());
|
||||
#endif
|
||||
SetPos (newPos);
|
||||
}
|
||||
|
||||
/// Sets the current write position to \p newPos
|
||||
inline void ostream::iseek (const_iterator newPos)
|
||||
{
|
||||
seek (distance (begin(), const_cast<iterator>(newPos)));
|
||||
}
|
||||
|
||||
/// Sets the current write position to \p p based on \p d.
|
||||
inline void ostream::seekp (off_t p, seekdir d)
|
||||
{
|
||||
switch (d) {
|
||||
case beg: seek (p); break;
|
||||
case cur: seek (pos() + p); break;
|
||||
case ios_base::end: seek (size() - p); break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Skips \p nBytes without writing anything.
|
||||
inline void ostream::skip (size_type nBytes)
|
||||
{
|
||||
seek (pos() + nBytes);
|
||||
}
|
||||
|
||||
/// Returns number of bytes remaining in the write buffer.
|
||||
inline ostream::size_type ostream::remaining (void) const
|
||||
{
|
||||
return (size() - pos());
|
||||
}
|
||||
|
||||
/// Returns \c true if the write pointer is aligned on \p grain
|
||||
inline bool ostream::aligned (size_type grain) const
|
||||
{
|
||||
assert (uintptr_t(begin()) % grain == 0 && "Streams should be attached aligned at the maximum element grain to avoid bus errors.");
|
||||
return (pos() % grain == 0);
|
||||
}
|
||||
|
||||
/// Returns the number of bytes to skip to be aligned on \p grain.
|
||||
inline ostream::size_type ostream::align_size (size_type grain) const
|
||||
{
|
||||
return (Align (pos(), grain) - pos());
|
||||
}
|
||||
|
||||
/// Writes the contents of \p buf into the stream as a raw dump.
|
||||
inline void ostream::write (const cmemlink& buf)
|
||||
{
|
||||
write (buf.begin(), buf.size());
|
||||
}
|
||||
|
||||
/// Writes type T into the stream via a direct pointer cast.
|
||||
template <typename T>
|
||||
inline void ostream::iwrite (const T& v)
|
||||
{
|
||||
assert (aligned (alignof (v)));
|
||||
#ifdef WANT_STREAM_BOUNDS_CHECKING
|
||||
verify_remaining ("write", typeid(v).name(), sizeof(T));
|
||||
#else
|
||||
assert (remaining() >= sizeof(T));
|
||||
#endif
|
||||
*reinterpret_cast<T*>(ipos()) = v;
|
||||
SetPos (pos() + sizeof(T));
|
||||
}
|
||||
|
||||
#define OSTREAM_OPERATOR(type) \
|
||||
inline ostream& operator<< (ostream& os, type v) { os.iwrite(v); return (os); }
|
||||
|
||||
template <typename T>
|
||||
OSTREAM_OPERATOR(T*)
|
||||
OSTREAM_OPERATOR(int8_t)
|
||||
OSTREAM_OPERATOR(uint8_t)
|
||||
OSTREAM_OPERATOR(int16_t)
|
||||
OSTREAM_OPERATOR(uint16_t)
|
||||
OSTREAM_OPERATOR(int32_t)
|
||||
OSTREAM_OPERATOR(uint32_t)
|
||||
OSTREAM_OPERATOR(float)
|
||||
OSTREAM_OPERATOR(double)
|
||||
OSTREAM_OPERATOR(wchar_t)
|
||||
#if SIZE_OF_BOOL == SIZE_OF_CHAR
|
||||
OSTREAM_OPERATOR(bool)
|
||||
#else
|
||||
inline ostream& operator<< (ostream& os, bool v)
|
||||
{ os.iwrite (uint8_t(v)); return (os); }
|
||||
#endif
|
||||
#if HAVE_THREE_CHAR_TYPES
|
||||
OSTREAM_OPERATOR(char)
|
||||
#endif
|
||||
#if HAVE_INT64_T
|
||||
OSTREAM_OPERATOR(int64_t)
|
||||
OSTREAM_OPERATOR(uint64_t)
|
||||
#endif
|
||||
#if SIZE_OF_LONG == SIZE_OF_INT
|
||||
OSTREAM_OPERATOR(long)
|
||||
OSTREAM_OPERATOR(unsigned long)
|
||||
#endif
|
||||
#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
|
||||
OSTREAM_OPERATOR(long long)
|
||||
OSTREAM_OPERATOR(unsigned long long)
|
||||
#endif
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// ofstream.cc
|
||||
//
|
||||
|
||||
#include "ofstream.h"
|
||||
#include "ustring.h"
|
||||
#include "uexception.h"
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
namespace ustl {
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
ifstream cin (STDIN_FILENO);
|
||||
ofstream cout (STDOUT_FILENO);
|
||||
ofstream cerr (STDERR_FILENO);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// Default constructor.
|
||||
ofstream::ofstream (void)
|
||||
: ostringstream (),
|
||||
m_File ()
|
||||
{
|
||||
reserve (255);
|
||||
}
|
||||
|
||||
/// Constructs a stream for writing to \p Fd.
|
||||
ofstream::ofstream (int Fd)
|
||||
: ostringstream (),
|
||||
m_File (Fd)
|
||||
{
|
||||
clear (m_File.rdstate());
|
||||
reserve (255);
|
||||
}
|
||||
|
||||
/// Constructs a stream for writing to \p filename.
|
||||
ofstream::ofstream (const char* filename, openmode mode)
|
||||
: ostringstream (),
|
||||
m_File (filename, mode)
|
||||
{
|
||||
clear (m_File.rdstate());
|
||||
}
|
||||
|
||||
/// Default destructor.
|
||||
ofstream::~ofstream (void)
|
||||
{
|
||||
#if PLATFORM_ANDROID
|
||||
flush();
|
||||
#else /* !PLATFORM_ANDROID */
|
||||
try { flush(); } catch (...) {}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Flushes the buffer to the file.
|
||||
void ofstream::flush (void)
|
||||
{
|
||||
while (pos() && overflow (remaining()));
|
||||
m_File.sync();
|
||||
clear (m_File.rdstate());
|
||||
}
|
||||
|
||||
/// Seeks to \p p based on \p d.
|
||||
void ofstream::seekp (off_t p, seekdir d)
|
||||
{
|
||||
flush();
|
||||
m_File.seekp (p, d);
|
||||
clear (m_File.rdstate());
|
||||
}
|
||||
|
||||
/// Called when more buffer space (\p n bytes) is needed.
|
||||
ofstream::size_type ofstream::overflow (size_type n)
|
||||
{
|
||||
if (eof() || (n > remaining() && n < capacity() - pos()))
|
||||
return (ostringstream::overflow (n));
|
||||
size_type bw = m_File.write (cdata(), pos());
|
||||
clear (m_File.rdstate());
|
||||
erase (begin(), bw);
|
||||
if (remaining() < n)
|
||||
ostringstream::overflow (n);
|
||||
return (remaining());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// Constructs a stream to read from \p Fd.
|
||||
ifstream::ifstream (int Fd)
|
||||
: istringstream (),
|
||||
m_Buffer (255),
|
||||
m_File (Fd)
|
||||
{
|
||||
link (m_Buffer.data(), 0U);
|
||||
}
|
||||
|
||||
/// Constructs a stream to read from \p filename.
|
||||
ifstream::ifstream (const char* filename, openmode mode)
|
||||
: istringstream (),
|
||||
m_Buffer (255),
|
||||
m_File (filename, mode)
|
||||
{
|
||||
clear (m_File.rdstate());
|
||||
link (m_Buffer.data(), 0U);
|
||||
}
|
||||
|
||||
/// Reads at least \p n more bytes and returns available bytes.
|
||||
ifstream::size_type ifstream::underflow (size_type n)
|
||||
{
|
||||
if (eof())
|
||||
return (istringstream::underflow (n));
|
||||
|
||||
const ssize_t freeSpace = m_Buffer.size() - pos();
|
||||
const ssize_t neededFreeSpace = max (n, m_Buffer.size() / 2);
|
||||
const size_t oughtToErase = Align (max (0, neededFreeSpace - freeSpace));
|
||||
const size_t nToErase = min (pos(), oughtToErase);
|
||||
m_Buffer.memlink::erase (m_Buffer.begin(), nToErase);
|
||||
const uoff_t oldPos (pos() - nToErase);
|
||||
|
||||
size_type br = oldPos;
|
||||
if (m_Buffer.size() - br < n) {
|
||||
m_Buffer.resize (br + neededFreeSpace);
|
||||
link (m_Buffer.data(), 0U);
|
||||
}
|
||||
cout.flush();
|
||||
|
||||
while (br - oldPos < n && m_File.good())
|
||||
br += m_File.readsome (m_Buffer.begin() + br, m_Buffer.size() - br);
|
||||
clear (m_File.rdstate());
|
||||
|
||||
m_Buffer[br] = string::c_Terminator;
|
||||
link (m_Buffer.data(), br);
|
||||
seek (oldPos);
|
||||
return (remaining());
|
||||
}
|
||||
|
||||
/// Flushes the input.
|
||||
void ifstream::sync (void)
|
||||
{
|
||||
istringstream::sync();
|
||||
underflow (0U);
|
||||
m_File.sync();
|
||||
clear (m_File.rdstate());
|
||||
}
|
||||
|
||||
/// Seeks to \p p based on \p d.
|
||||
void ifstream::seekg (off_t p, seekdir d)
|
||||
{
|
||||
m_Buffer.clear();
|
||||
link (m_Buffer);
|
||||
m_File.seekg (p, d);
|
||||
clear (m_File.rdstate());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// ofstream.h
|
||||
//
|
||||
|
||||
#ifndef FDOSTREAM_H_5E27FC3D530BF3CA04D6C73F5700EECC
|
||||
#define FDOSTREAM_H_5E27FC3D530BF3CA04D6C73F5700EECC
|
||||
|
||||
#include "sistream.h"
|
||||
#include "sostream.h"
|
||||
#include "fstream.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// \class ofstream fdostream.h ustl.h
|
||||
/// \ingroup DeviceStreams
|
||||
/// \brief A string stream that writes to an fd. Implements cout and cerr.
|
||||
class ofstream : public ostringstream {
|
||||
public:
|
||||
ofstream (void);
|
||||
explicit ofstream (int Fd);
|
||||
explicit ofstream (const char* filename, openmode mode = out);
|
||||
virtual ~ofstream (void);
|
||||
inline void open (const char* filename, openmode mode = out) { m_File.open (filename, mode); clear (m_File.rdstate()); }
|
||||
inline void close (void) { m_File.close(); clear (m_File.rdstate()); }
|
||||
inline bool is_open (void) const { return (m_File.is_open()); }
|
||||
inline iostate exceptions (iostate v) { ostringstream::exceptions(v); return (m_File.exceptions(v)); }
|
||||
inline void setstate (iostate v) { ostringstream::setstate(v); m_File.setstate(v); }
|
||||
inline void clear (iostate v = goodbit) { ostringstream::clear(v); m_File.clear(v); }
|
||||
inline off_t tellp (void) const { return (m_File.tellp() + ostringstream::tellp()); }
|
||||
inline int fd (void) const { return (m_File.fd()); }
|
||||
inline void stat (struct stat& rs) const { m_File.stat (rs); }
|
||||
inline void set_nonblock (bool v = true) { m_File.set_nonblock (v); }
|
||||
inline int ioctl (const char* rname, int request, long argument = 0) { return (m_File.ioctl (rname, request, argument)); }
|
||||
inline int ioctl (const char* rname, int request, int argument) { return (m_File.ioctl (rname, request, argument)); }
|
||||
inline int ioctl (const char* rname, int request, void* argument) { return (m_File.ioctl (rname, request, argument)); }
|
||||
void seekp (off_t p, seekdir d = beg);
|
||||
void flush (void);
|
||||
virtual size_type overflow (size_type n = 1);
|
||||
private:
|
||||
fstream m_File;
|
||||
};
|
||||
|
||||
/// \class ifstream fdostream.h ustl.h
|
||||
/// \ingroup DeviceStreams
|
||||
/// \brief A string stream that reads from an fd. Implements cin.
|
||||
class ifstream : public istringstream {
|
||||
public:
|
||||
ifstream (void);
|
||||
explicit ifstream (int Fd);
|
||||
explicit ifstream (const char* filename, openmode mode = in);
|
||||
inline void open (const char* filename, openmode mode = in) { m_File.open (filename, mode); clear (m_File.rdstate()); }
|
||||
inline void close (void) { m_File.close(); clear (m_File.rdstate()); }
|
||||
inline bool is_open (void) const { return (m_File.is_open()); }
|
||||
inline iostate exceptions (iostate v) { istringstream::exceptions(v); return (m_File.exceptions(v)); }
|
||||
inline void setstate (iostate v) { istringstream::setstate(v); m_File.setstate(v); }
|
||||
inline void clear (iostate v = goodbit) { istringstream::clear(v); m_File.clear(v); }
|
||||
inline off_t tellg (void) const { return (m_File.tellg() - remaining()); }
|
||||
inline int fd (void) const { return (m_File.fd()); }
|
||||
inline void stat (struct stat& rs) const { m_File.stat (rs); }
|
||||
inline void set_nonblock (bool v = true) { m_File.set_nonblock (v); }
|
||||
inline int ioctl (const char* rname, int request, long argument = 0) { return (m_File.ioctl (rname, request, argument)); }
|
||||
inline int ioctl (const char* rname, int request, int argument) { return (m_File.ioctl (rname, request, argument)); }
|
||||
inline int ioctl (const char* rname, int request, void* argument) { return (m_File.ioctl (rname, request, argument)); }
|
||||
void seekg (off_t p, seekdir d = beg);
|
||||
void sync (void);
|
||||
virtual size_type underflow (size_type n = 1);
|
||||
private:
|
||||
string m_Buffer;
|
||||
fstream m_File;
|
||||
};
|
||||
|
||||
extern ofstream cout, cerr;
|
||||
extern ifstream cin;
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,465 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
/// \file simd.h
|
||||
/// \brief SIMD-type algorithms, with hardware acceleration, if available.
|
||||
///
|
||||
/// All algorithms are container-based because iterator syntax is just too
|
||||
/// damn verbose and because the specializations need to be able to tell
|
||||
/// how many elements are in the container in order to choose proper SIMD
|
||||
/// instruction set (i.e.: 4 floats select SSE, while 2 floats select 3dNow!)
|
||||
/// Specializations are only for the tuple template because the container
|
||||
/// must be of a fixed and compile-time-known size for the compiler to be
|
||||
/// able to choose the specialization.
|
||||
///
|
||||
|
||||
#ifndef SIMD_H_39BE2D970DF4BD00508CCFFB482496F9
|
||||
#define SIMD_H_39BE2D970DF4BD00508CCFFB482496F9
|
||||
|
||||
#include "uassert.h"
|
||||
#include "ulimits.h"
|
||||
#if HAVE_MATH_H
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
#include <stdio.h>
|
||||
#undef CPU_HAS_MMX
|
||||
#endif
|
||||
|
||||
namespace ustl {
|
||||
namespace simd {
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Generic algorithms
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// Applies \p op to each element in \p op1.
|
||||
template <typename Ctr, typename UnaryOperation>
|
||||
inline void packop (Ctr& op1, UnaryOperation op)
|
||||
{
|
||||
foreach (typename Ctr::iterator, i, op1)
|
||||
op (*i);
|
||||
}
|
||||
|
||||
/// Applies \p op to each element in \p op1 and \p op2 and stores in \p op2.
|
||||
template <typename Ctr, typename BinaryOperation>
|
||||
inline void packop (const Ctr& op1, Ctr& op2, BinaryOperation op)
|
||||
{
|
||||
assert (op2.size() <= op1.size());
|
||||
typename Ctr::const_iterator i1 (op1.begin());
|
||||
typename Ctr::iterator i2 (op2.begin());
|
||||
for (; i2 != op2.end(); ++i1, ++i2)
|
||||
*i2 = op (*i2, *i1);
|
||||
}
|
||||
|
||||
/// Applies \p op to corresponding elements in \p op1 and \p op2 and stores in \p result.
|
||||
template <typename Ctr, typename BinaryOperation>
|
||||
inline void packop (const Ctr& op1, const Ctr& op2, Ctr& result, BinaryOperation op)
|
||||
{
|
||||
assert (op1.size() <= op2.size() && op1.size() <= result.size());
|
||||
passign (op1, result);
|
||||
packop (op2, result);
|
||||
}
|
||||
|
||||
/// Copies \p op1 into \p result.
|
||||
template <typename Ctr>
|
||||
inline void passign (const Ctr& op1, Ctr& result)
|
||||
{
|
||||
assert (op1.size() <= result.size());
|
||||
typename Ctr::iterator d (result.begin());
|
||||
foreach (typename Ctr::const_iterator, s, op1)
|
||||
*d++ = *s;
|
||||
}
|
||||
|
||||
/// Copies \p result.size() elements from \p op1 to \p result.
|
||||
template <typename Ctr>
|
||||
inline void ipassign (typename Ctr::const_iterator op1, Ctr& result)
|
||||
{
|
||||
foreach (typename Ctr::iterator, d, result)
|
||||
*d = *op1++;
|
||||
}
|
||||
|
||||
template <typename Ctr1, typename Ctr2, typename ConvertFunction>
|
||||
inline void pconvert (const Ctr1& op1, Ctr2& op2, ConvertFunction f)
|
||||
{
|
||||
assert (op1.size() <= op2.size());
|
||||
typename Ctr1::const_iterator i1 (op1.begin());
|
||||
typename Ctr2::iterator i2 (op2.begin());
|
||||
for (; i1 != op1.end(); ++i1, ++i2)
|
||||
*i2 = f (*i1);
|
||||
}
|
||||
|
||||
// Functionoids for SIMD operations, like saturation arithmetic, shifts, etc.
|
||||
STD_BINARY_FUNCTOR (fpadds, T, ((b > numeric_limits<T>::max() - a) ? numeric_limits<T>::max() : a + b))
|
||||
STD_BINARY_FUNCTOR (fpsubs, T, ((a < numeric_limits<T>::min() + b) ? numeric_limits<T>::min() : a - b))
|
||||
STD_BINARY_FUNCTOR (fpshl, T, (a << b))
|
||||
STD_BINARY_FUNCTOR (fpshr, T, (a >> b))
|
||||
STD_BINARY_FUNCTOR (fpmin, T, (min (a, b)))
|
||||
STD_BINARY_FUNCTOR (fpmax, T, (max (a, b)))
|
||||
STD_BINARY_FUNCTOR (fpavg, T, ((a + b + 1) / 2))
|
||||
STD_CONVERSION_FUNCTOR (fcast, (D(a)))
|
||||
#if HAVE_MATH_H
|
||||
STD_UNARY_FUNCTOR (fpreciprocal,T, (1 / a))
|
||||
STD_UNARY_FUNCTOR (fpsqrt, T, (reset_mmx(), T (sqrt (a))))
|
||||
STD_UNARY_FUNCTOR (fprecipsqrt, T, (reset_mmx(), 1 / T(sqrt (a))))
|
||||
STD_UNARY_FUNCTOR (fsin, T, (reset_mmx(), T (sin (a))))
|
||||
STD_UNARY_FUNCTOR (fcos, T, (reset_mmx(), T (cos (a))))
|
||||
STD_UNARY_FUNCTOR (ftan, T, (reset_mmx(), T (tan (a))))
|
||||
#if HAVE_RINTF
|
||||
STD_CONVERSION_FUNCTOR (fround, (reset_mmx(), D(rintf(a))))
|
||||
#else
|
||||
STD_CONVERSION_FUNCTOR (fround, (reset_mmx(), D(rint(a))))
|
||||
#endif
|
||||
template <> inline int32_t fround<double,int32_t>::operator()(const double& a) const { reset_mmx(); return (int32_t(rint(a))); }
|
||||
#endif
|
||||
template <> inline float fpavg<float>::operator()(const float& a, const float& b) const { return ((a + b) / 2); }
|
||||
template <> inline double fpavg<double>::operator()(const double& a, const double& b) const { return ((a + b) / 2); }
|
||||
|
||||
#define SIMD_PACKEDOP1(name, operation) \
|
||||
template <typename Ctr> \
|
||||
inline void name (Ctr& op1) \
|
||||
{ \
|
||||
typedef typename Ctr::value_type value_t; \
|
||||
packop (op1, operation<value_t>()); \
|
||||
}
|
||||
#define SIMD_PACKEDOP2(name, operation) \
|
||||
template <typename Ctr> \
|
||||
inline void name (const Ctr& op1, Ctr& op2) \
|
||||
{ \
|
||||
typedef typename Ctr::value_type value_t; \
|
||||
packop (op1, op2, operation<value_t>()); \
|
||||
}
|
||||
#define SIMD_PACKEDOP3(name, operation) \
|
||||
template <typename Ctr> \
|
||||
inline void name (const Ctr& op1, const Ctr& op2, Ctr& result) \
|
||||
{ \
|
||||
typedef typename Ctr::value_type value_t; \
|
||||
packop (op1, op2, result, operation<value_t>()); \
|
||||
}
|
||||
#define SIMD_SINGLEOP1(name, operation) \
|
||||
template <typename T> \
|
||||
inline T name (T op) \
|
||||
{ \
|
||||
operation<T> obj; \
|
||||
return (obj(op)); \
|
||||
}
|
||||
#define SIMD_CONVERTOP(name, operation) \
|
||||
template <typename Ctr1, typename Ctr2> \
|
||||
inline void name (const Ctr1& op1, Ctr2& op2) \
|
||||
{ \
|
||||
typedef typename Ctr1::value_type value1_t; \
|
||||
typedef typename Ctr2::value_type value2_t; \
|
||||
pconvert (op1, op2, operation<value1_t, value2_t>());\
|
||||
}
|
||||
|
||||
SIMD_PACKEDOP2 (padd, plus)
|
||||
SIMD_PACKEDOP2 (psub, minus)
|
||||
SIMD_PACKEDOP2 (pmul, multiplies)
|
||||
SIMD_PACKEDOP2 (pdiv, divides)
|
||||
SIMD_PACKEDOP2 (pand, bitwise_and)
|
||||
SIMD_PACKEDOP2 (por, bitwise_or)
|
||||
SIMD_PACKEDOP2 (pxor, bitwise_xor)
|
||||
SIMD_PACKEDOP2 (pshl, fpshl)
|
||||
SIMD_PACKEDOP2 (pshr, fpshr)
|
||||
SIMD_PACKEDOP2 (psubs, fpsubs)
|
||||
SIMD_PACKEDOP2 (pmin, fpmin)
|
||||
SIMD_PACKEDOP2 (pmax, fpmax)
|
||||
SIMD_PACKEDOP2 (pavg, fpavg)
|
||||
|
||||
SIMD_PACKEDOP3 (padd, plus)
|
||||
SIMD_PACKEDOP3 (psub, minus)
|
||||
SIMD_PACKEDOP3 (pmul, multiplies)
|
||||
SIMD_PACKEDOP3 (pdiv, divides)
|
||||
SIMD_PACKEDOP3 (pand, bitwise_and)
|
||||
SIMD_PACKEDOP3 (por, bitwise_or)
|
||||
SIMD_PACKEDOP3 (pxor, bitwise_xor)
|
||||
SIMD_PACKEDOP3 (pshl, fpshl)
|
||||
SIMD_PACKEDOP3 (pshr, fpshr)
|
||||
SIMD_PACKEDOP3 (padds, fpadds)
|
||||
SIMD_PACKEDOP3 (psubs, fpsubs)
|
||||
SIMD_PACKEDOP3 (pmin, fpmin)
|
||||
SIMD_PACKEDOP3 (pmax, fpmax)
|
||||
SIMD_PACKEDOP3 (pavg, fpavg)
|
||||
|
||||
#if HAVE_MATH_H
|
||||
SIMD_PACKEDOP1 (precip, fpreciprocal)
|
||||
SIMD_PACKEDOP1 (psqrt, fpsqrt)
|
||||
SIMD_PACKEDOP1 (precipsqrt, fprecipsqrt)
|
||||
SIMD_PACKEDOP1 (psin, fsin)
|
||||
SIMD_PACKEDOP1 (pcos, fcos)
|
||||
SIMD_PACKEDOP1 (ptan, ftan)
|
||||
|
||||
SIMD_SINGLEOP1 (srecip, fpreciprocal)
|
||||
SIMD_SINGLEOP1 (ssqrt, fpsqrt)
|
||||
SIMD_SINGLEOP1 (srecipsqrt, fprecipsqrt)
|
||||
SIMD_SINGLEOP1 (ssin, fsin)
|
||||
SIMD_SINGLEOP1 (scos, fcos)
|
||||
SIMD_SINGLEOP1 (stan, ftan)
|
||||
|
||||
SIMD_CONVERTOP (pround, fround)
|
||||
|
||||
template <typename T> inline int32_t sround (T op) { fround<T,int32_t> obj; return (obj (op)); }
|
||||
#endif
|
||||
|
||||
#undef SIMD_SINGLEOP1
|
||||
#undef SIMD_PACKEDOP3
|
||||
#undef SIMD_PACKEDOP2
|
||||
#undef SIMD_PACKEDOP1
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Vector types to cast tuple data to
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#if HAVE_VECTOR_EXTENSIONS && __GNUC__ >= 4
|
||||
#define VECTOR_ATTRIBUTE(mode,vs) __attribute__((vector_size(vs)))
|
||||
#else
|
||||
#define VECTOR_ATTRIBUTE(mode,vs)
|
||||
#endif
|
||||
typedef uint8_t v8qi_t VECTOR_ATTRIBUTE (V8QI,8);
|
||||
typedef uint16_t v4hi_t VECTOR_ATTRIBUTE (V4HI,8);
|
||||
typedef uint16_t v8hi_t VECTOR_ATTRIBUTE (V8HI,16);
|
||||
typedef uint32_t v2si_t VECTOR_ATTRIBUTE (V2SI,8);
|
||||
typedef uint32_t v4si_t VECTOR_ATTRIBUTE (V4SI,16);
|
||||
#if HAVE_INT64_T
|
||||
typedef uint64_t v1di_t VECTOR_ATTRIBUTE (V1DI,8);
|
||||
#endif
|
||||
typedef float v2sf_t VECTOR_ATTRIBUTE (V2SF,8);
|
||||
typedef float v4sf_t VECTOR_ATTRIBUTE (V4SF,16);
|
||||
typedef double v2df_t VECTOR_ATTRIBUTE (V2DF,16);
|
||||
#undef VECTOR_ATTRIBUTE
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Hardware accelerated specializations
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#define SIMD_PKOP2_SPEC(n, type, optype) \
|
||||
template <> \
|
||||
inline void packop (const tuple<n,type>& oin, tuple<n,type>& oout, optype<type>)
|
||||
#define SIMD_PASSIGN_SPEC(n, type) \
|
||||
template <> \
|
||||
inline void passign (const tuple<n,type>& oin, tuple<n,type>& oout)
|
||||
#define SIMD_IPASSIGN_SPEC(n, type) \
|
||||
template <> \
|
||||
inline void ipassign (tuple<n,type>::const_iterator oin, tuple<n,type>& oout)
|
||||
#define SIMD_CONVERT_SPEC(n, type1, type2, optype) \
|
||||
template <> \
|
||||
inline void pconvert (const tuple<n,type1>& oin, tuple<n,type2>& oout, optype<type1,type2>)
|
||||
|
||||
#if CPU_HAS_MMX
|
||||
#define STD_MMX_ARGS "=m"(oout[0]) : "m"(oin[0]) : "mm0", "st", "memory"
|
||||
#define DBL_MMX_ARGS "=m"(oout[0]), "=m"(oout[2]) : "m"(oin[0]), "m"(oin[2]) : "mm0", "mm1", "st", "st(1)", "memory"
|
||||
#define MMX_PKOP2_SPEC(n,type,optype,instruction) \
|
||||
SIMD_PKOP2_SPEC(n,type,optype) \
|
||||
{ asm ("movq %0, %%mm0\n\t" #instruction " %1, %%mm0\n\tmovq %%mm0, %0" : STD_MMX_ARGS); reset_mmx(); }
|
||||
#define MMX_DBL_PKOP2_SPEC(n,type,optype,instruction) \
|
||||
SIMD_PKOP2_SPEC(n,type,optype) \
|
||||
{ asm ("movq %0, %%mm0\n\tmovq %1, %%mm1\n\t" #instruction " %2, %%mm0\n\t" #instruction " %3, %%mm1\n\tmovq %%mm0, %0\n\tmovq %%mm1, %1" : DBL_MMX_ARGS); reset_mmx(); }
|
||||
#define MMX_PASSIGN_SPEC(n,type) \
|
||||
SIMD_PASSIGN_SPEC(n,type) \
|
||||
{ asm ("movq %1, %%mm0\n\tmovq %%mm0, %0" : STD_MMX_ARGS); reset_mmx(); }
|
||||
#define MMX_DBL_PASSIGN_SPEC(n,type) \
|
||||
SIMD_PASSIGN_SPEC(n,type) \
|
||||
{ asm ("movq %2, %%mm0\n\tmovq %3, %%mm1\n\tmovq %%mm0, %0\n\tmovq %%mm1, %1" : DBL_MMX_ARGS); reset_mmx(); }
|
||||
#define MMX_IPASSIGN_SPEC(n,type) \
|
||||
SIMD_IPASSIGN_SPEC(n,type) \
|
||||
{ asm ("movq %1, %%mm0\n\tmovq %%mm0, %0" : STD_MMX_ARGS); reset_mmx(); }
|
||||
#define MMX_DBL_IPASSIGN_SPEC(n,type) \
|
||||
SIMD_IPASSIGN_SPEC(n,type) \
|
||||
{ asm ("movq %2, %%mm0\n\tmovq %3, %%mm1\n\tmovq %%mm0, %0\n\tmovq %%mm1, %1" : DBL_MMX_ARGS); reset_mmx(); }
|
||||
|
||||
MMX_PASSIGN_SPEC(8,uint8_t)
|
||||
MMX_PKOP2_SPEC(8,uint8_t,plus,paddb)
|
||||
MMX_PKOP2_SPEC(8,uint8_t,minus,psubb)
|
||||
MMX_PKOP2_SPEC(8,uint8_t,bitwise_and,pand)
|
||||
MMX_PKOP2_SPEC(8,uint8_t,bitwise_or,por)
|
||||
MMX_PKOP2_SPEC(8,uint8_t,bitwise_xor,pxor)
|
||||
MMX_PKOP2_SPEC(8,uint8_t,fpadds,paddusb)
|
||||
MMX_PKOP2_SPEC(8,uint8_t,fpsubs,psubusb)
|
||||
|
||||
MMX_PASSIGN_SPEC(8,int8_t)
|
||||
MMX_PKOP2_SPEC(8,int8_t,plus,paddb)
|
||||
MMX_PKOP2_SPEC(8,int8_t,minus,psubb)
|
||||
MMX_PKOP2_SPEC(8,int8_t,bitwise_and,pand)
|
||||
MMX_PKOP2_SPEC(8,int8_t,bitwise_or,por)
|
||||
MMX_PKOP2_SPEC(8,int8_t,bitwise_xor,pxor)
|
||||
MMX_PKOP2_SPEC(8,int8_t,fpadds,paddsb)
|
||||
MMX_PKOP2_SPEC(8,int8_t,fpsubs,psubsb)
|
||||
|
||||
MMX_PASSIGN_SPEC(4,uint16_t)
|
||||
MMX_PKOP2_SPEC(4,uint16_t,plus,paddw)
|
||||
MMX_PKOP2_SPEC(4,uint16_t,minus,psubw)
|
||||
MMX_PKOP2_SPEC(4,uint16_t,bitwise_and,pand)
|
||||
MMX_PKOP2_SPEC(4,uint16_t,bitwise_or,por)
|
||||
MMX_PKOP2_SPEC(4,uint16_t,bitwise_xor,pxor)
|
||||
/// \todo psllw does not work like other operations, it uses the first element for shift count.
|
||||
//MMX_PKOP2_SPEC(4,uint16_t,fpshl,psllw)
|
||||
//MMX_PKOP2_SPEC(4,uint16_t,fpshr,psrlw)
|
||||
MMX_PKOP2_SPEC(4,uint16_t,fpadds,paddusw)
|
||||
MMX_PKOP2_SPEC(4,uint16_t,fpsubs,psubusw)
|
||||
|
||||
MMX_PASSIGN_SPEC(4,int16_t)
|
||||
MMX_PKOP2_SPEC(4,int16_t,plus,paddw)
|
||||
MMX_PKOP2_SPEC(4,int16_t,minus,psubw)
|
||||
MMX_PKOP2_SPEC(4,int16_t,bitwise_and,pand)
|
||||
MMX_PKOP2_SPEC(4,int16_t,bitwise_or,por)
|
||||
MMX_PKOP2_SPEC(4,int16_t,bitwise_xor,pxor)
|
||||
//MMX_PKOP2_SPEC(4,int16_t,fpshl,psllw)
|
||||
//MMX_PKOP2_SPEC(4,int16_t,fpshr,psrlw)
|
||||
MMX_PKOP2_SPEC(4,int16_t,fpadds,paddsw)
|
||||
MMX_PKOP2_SPEC(4,int16_t,fpsubs,psubsw)
|
||||
|
||||
MMX_PASSIGN_SPEC(2,uint32_t)
|
||||
MMX_PKOP2_SPEC(2,uint32_t,plus,paddd)
|
||||
MMX_PKOP2_SPEC(2,uint32_t,minus,psubd)
|
||||
MMX_PKOP2_SPEC(2,uint32_t,bitwise_and,pand)
|
||||
MMX_PKOP2_SPEC(2,uint32_t,bitwise_or,por)
|
||||
MMX_PKOP2_SPEC(2,uint32_t,bitwise_xor,pxor)
|
||||
//MMX_PKOP2_SPEC(2,uint32_t,fpshl,pslld)
|
||||
//MMX_PKOP2_SPEC(2,uint32_t,fpshr,psrld)
|
||||
|
||||
MMX_PASSIGN_SPEC(2,int32_t)
|
||||
MMX_PKOP2_SPEC(2,int32_t,plus,paddd)
|
||||
MMX_PKOP2_SPEC(2,int32_t,minus,psubd)
|
||||
MMX_PKOP2_SPEC(2,int32_t,bitwise_and,pand)
|
||||
MMX_PKOP2_SPEC(2,int32_t,bitwise_or,por)
|
||||
MMX_PKOP2_SPEC(2,int32_t,bitwise_xor,pxor)
|
||||
//MMX_PKOP2_SPEC(2,int32_t,fpshl,pslld)
|
||||
//MMX_PKOP2_SPEC(2,int32_t,fpshr,psrld)
|
||||
|
||||
MMX_DBL_PKOP2_SPEC(4,uint32_t,plus,paddd)
|
||||
MMX_DBL_PKOP2_SPEC(4,uint32_t,minus,psubd)
|
||||
MMX_DBL_PKOP2_SPEC(4,uint32_t,bitwise_and,pand)
|
||||
MMX_DBL_PKOP2_SPEC(4,uint32_t,bitwise_or,por)
|
||||
MMX_DBL_PKOP2_SPEC(4,uint32_t,bitwise_xor,pxor)
|
||||
//MMX_DBL_PKOP2_SPEC(2,uint32_t,fpshl,pslld)
|
||||
//MMX_DBL_PKOP2_SPEC(2,uint32_t,fpshr,psrld)
|
||||
|
||||
MMX_DBL_PKOP2_SPEC(4,int32_t,plus,paddd)
|
||||
MMX_DBL_PKOP2_SPEC(4,int32_t,minus,psubd)
|
||||
MMX_DBL_PKOP2_SPEC(4,int32_t,bitwise_and,pand)
|
||||
MMX_DBL_PKOP2_SPEC(4,int32_t,bitwise_or,por)
|
||||
MMX_DBL_PKOP2_SPEC(4,int32_t,bitwise_xor,pxor)
|
||||
//MMX_DBL_PKOP2_SPEC(2,int32_t,fpshl,pslld)
|
||||
//MMX_DBL_PKOP2_SPEC(2,int32_t,fpshr,psrld)
|
||||
|
||||
#if CPU_HAS_SSE || CPU_HAS_3DNOW
|
||||
MMX_PKOP2_SPEC(8,uint8_t,fpavg,pavgb)
|
||||
MMX_PKOP2_SPEC(8,int8_t,fpavg,pavgb)
|
||||
MMX_PKOP2_SPEC(4,uint16_t,fpavg,pavgw)
|
||||
MMX_PKOP2_SPEC(4,int16_t,fpavg,pavgw)
|
||||
MMX_PKOP2_SPEC(8,uint8_t,fpmin,pminub)
|
||||
MMX_PKOP2_SPEC(8,uint8_t,fpmax,pmaxub)
|
||||
MMX_PKOP2_SPEC(4,int16_t,fpmax,pmaxsw)
|
||||
MMX_PKOP2_SPEC(4,int16_t,fpmin,pminsw)
|
||||
#endif // CPU_HAS_SSE || CPU_HAS_3DNOW
|
||||
|
||||
#if CPU_HAS_3DNOW
|
||||
MMX_PASSIGN_SPEC(2,float)
|
||||
MMX_PKOP2_SPEC(2,float,plus,pfadd)
|
||||
MMX_PKOP2_SPEC(2,float,minus,pfsub)
|
||||
MMX_PKOP2_SPEC(2,float,multiplies,pfmul)
|
||||
MMX_PKOP2_SPEC(2,float,fpmin,pfmin)
|
||||
MMX_PKOP2_SPEC(2,float,fpmax,pfmax)
|
||||
#ifndef CPU_HAS_SSE
|
||||
MMX_DBL_PKOP2_SPEC(4,float,plus,pfadd)
|
||||
MMX_DBL_PKOP2_SPEC(4,float,minus,pfsub)
|
||||
MMX_DBL_PKOP2_SPEC(4,float,multiplies,pfmul)
|
||||
MMX_DBL_PKOP2_SPEC(4,float,fpmin,pfmin)
|
||||
MMX_DBL_PKOP2_SPEC(4,float,fpmax,pfmax)
|
||||
#endif
|
||||
#endif // CPU_HAS_3DNOW
|
||||
|
||||
MMX_IPASSIGN_SPEC(8,uint8_t)
|
||||
MMX_IPASSIGN_SPEC(4,uint16_t)
|
||||
MMX_IPASSIGN_SPEC(2,uint32_t)
|
||||
MMX_IPASSIGN_SPEC(2,float)
|
||||
|
||||
#ifndef CPU_HAS_SSE
|
||||
MMX_DBL_PASSIGN_SPEC(4,float)
|
||||
MMX_DBL_PASSIGN_SPEC(4,uint32_t)
|
||||
MMX_DBL_PASSIGN_SPEC(4,int32_t)
|
||||
MMX_DBL_IPASSIGN_SPEC(4,float)
|
||||
MMX_DBL_IPASSIGN_SPEC(4,uint32_t)
|
||||
MMX_DBL_IPASSIGN_SPEC(4,int32_t)
|
||||
#endif
|
||||
|
||||
#undef MMX_IPASSIGN_SPEC
|
||||
#undef MMX_PASSIGN_SPEC
|
||||
#undef MMX_PKOP2_SPEC
|
||||
#undef STD_MMX_ARGS
|
||||
#endif // CPU_HAS_MMX
|
||||
|
||||
#if CPU_HAS_SSE
|
||||
#define STD_SSE_ARGS "=m"(oout[0]) : "m"(oin[0]) : "xmm0", "memory"
|
||||
#define SSE_PKOP2_SPEC(n,type,optype,instruction) \
|
||||
SIMD_PKOP2_SPEC(n,type,optype) \
|
||||
{ asm ("movups %0, %%xmm0\n\tmovups %1, %%xmm1\n\t" #instruction " %%xmm1, %%xmm0\n\tmovups %%xmm0, %0" : STD_SSE_ARGS);}
|
||||
#define SSE_PASSIGN_SPEC(n,type) \
|
||||
SIMD_PASSIGN_SPEC(n,type) \
|
||||
{ asm ("movups %1, %%xmm0\n\tmovups %%xmm0, %0" : STD_SSE_ARGS);}
|
||||
#define SSE_IPASSIGN_SPEC(n,type) \
|
||||
SIMD_IPASSIGN_SPEC(n,type) \
|
||||
{ asm ("movups %1, %%xmm0\n\tmovups %%xmm0, %0" : STD_SSE_ARGS);}
|
||||
SSE_PASSIGN_SPEC(4,float)
|
||||
SSE_PASSIGN_SPEC(4,int32_t)
|
||||
SSE_PASSIGN_SPEC(4,uint32_t)
|
||||
SSE_PKOP2_SPEC(4,float,plus,addps)
|
||||
SSE_PKOP2_SPEC(4,float,minus,subps)
|
||||
SSE_PKOP2_SPEC(4,float,multiplies,mulps)
|
||||
SSE_PKOP2_SPEC(4,float,divides,divps)
|
||||
SSE_PKOP2_SPEC(4,float,bitwise_and,andps)
|
||||
SSE_PKOP2_SPEC(4,float,bitwise_or,orps)
|
||||
SSE_PKOP2_SPEC(4,float,bitwise_xor,xorps)
|
||||
SSE_PKOP2_SPEC(4,float,fpmax,maxps)
|
||||
SSE_PKOP2_SPEC(4,float,fpmin,minps)
|
||||
|
||||
SIMD_CONVERT_SPEC(4,float,int32_t,fround) {
|
||||
asm ("cvtps2pi %2, %%mm0\n\t"
|
||||
"cvtps2pi %3, %%mm1\n\t"
|
||||
"movq %%mm0, %0\n\t"
|
||||
"movq %%mm1, %1"
|
||||
: DBL_MMX_ARGS);
|
||||
reset_mmx();
|
||||
}
|
||||
SIMD_CONVERT_SPEC(4,int32_t,float,fround) {
|
||||
asm ("cvtpi2ps %2, %%xmm0\n\t"
|
||||
"shufps $0x4E,%%xmm0,%%xmm0\n\t"
|
||||
"cvtpi2ps %1, %%xmm0\n\t"
|
||||
"movups %%xmm0, %0"
|
||||
: "=m"(oout[0]) : "m"(oin[0]), "m"(oin[2]) : "xmm0", "memory");
|
||||
}
|
||||
template <> inline int32_t fround<float,int32_t>::operator()(const float& a) const {
|
||||
register int32_t rv;
|
||||
asm ("movss %1, %%xmm0\n\t"
|
||||
"cvtss2si %%xmm0, %0"
|
||||
: "=r"(rv) : "m"(a) : "xmm0" );
|
||||
return (rv);
|
||||
}
|
||||
template <> inline uint32_t fround<float,uint32_t>::operator()(const float& a) const {
|
||||
register uint32_t rv;
|
||||
asm ("movss %1, %%xmm0\n\t"
|
||||
"cvtss2si %%xmm0, %0"
|
||||
: "=r"(rv) : "m"(a) : "xmm0" );
|
||||
return (rv);
|
||||
}
|
||||
|
||||
SSE_IPASSIGN_SPEC(4,float)
|
||||
SSE_IPASSIGN_SPEC(4,int32_t)
|
||||
SSE_IPASSIGN_SPEC(4,uint32_t)
|
||||
|
||||
#undef SSE_IPASSIGN_SPEC
|
||||
#undef SSE_PASSIGN_SPEC
|
||||
#undef SSE_PKOP2_SPEC
|
||||
#undef STD_SSE_ARGS
|
||||
#endif // CPU_HAS_SSE
|
||||
|
||||
#undef SIMD_PACKEDOP_SPEC
|
||||
|
||||
} // namespace simd
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,237 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// sistream.cc
|
||||
//
|
||||
|
||||
#include "sistream.h"
|
||||
#include "sostream.h"
|
||||
#include "uassert.h"
|
||||
#include "ustring.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
const char ios_base::c_DefaultDelimiters [istringstream::c_MaxDelimiters] = " \t\n\r;:,.?";
|
||||
|
||||
/// Default constructor.
|
||||
istringstream::istringstream (void)
|
||||
: istream (),
|
||||
m_Base (0)
|
||||
{
|
||||
set_delimiters (c_DefaultDelimiters);
|
||||
}
|
||||
|
||||
istringstream::istringstream (const void* p, size_type n)
|
||||
: istream (),
|
||||
m_Base (0)
|
||||
{
|
||||
link (p, n);
|
||||
set_delimiters (c_DefaultDelimiters);
|
||||
}
|
||||
|
||||
istringstream::istringstream (const cmemlink& source)
|
||||
: istream (),
|
||||
m_Base (0)
|
||||
{
|
||||
link (source);
|
||||
set_delimiters (c_DefaultDelimiters);
|
||||
}
|
||||
|
||||
/// Sets delimiters to the contents of \p delimiters.
|
||||
void istringstream::set_delimiters (const char* delimiters)
|
||||
{
|
||||
fill (VectorRange (m_Delimiters), '\0');
|
||||
strncpy (m_Delimiters, delimiters, VectorSize(m_Delimiters)-1);
|
||||
}
|
||||
|
||||
inline bool istringstream::is_delimiter (char c) const
|
||||
{
|
||||
return (memchr (m_Delimiters, c, VectorSize(m_Delimiters)-1));
|
||||
}
|
||||
|
||||
char istringstream::skip_delimiters (void)
|
||||
{
|
||||
char c = m_Delimiters[0];
|
||||
while (is_delimiter(c) && (remaining() || underflow()))
|
||||
istream::iread (c);
|
||||
return (c);
|
||||
}
|
||||
|
||||
void istringstream::iread (int8_t& v)
|
||||
{
|
||||
v = skip_delimiters();
|
||||
}
|
||||
|
||||
typedef istringstream::iterator issiter_t;
|
||||
template <typename T>
|
||||
inline void str_to_num (issiter_t i, issiter_t* iend, uint8_t base, T& v)
|
||||
{ v = strtol (i, const_cast<char**>(iend), base); }
|
||||
template <> inline void str_to_num (issiter_t i, issiter_t* iend, uint8_t, double& v)
|
||||
{ v = strtod (i, const_cast<char**>(iend)); }
|
||||
#ifdef HAVE_LONG_LONG
|
||||
template <> inline void str_to_num (issiter_t i, issiter_t* iend, uint8_t base, long long& v)
|
||||
{ v = strtoll (i, const_cast<char**>(iend), base); }
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
inline void istringstream::read_number (T& v)
|
||||
{
|
||||
v = 0;
|
||||
if (skip_delimiters() == m_Delimiters[0])
|
||||
return;
|
||||
ungetc();
|
||||
iterator ilast;
|
||||
do {
|
||||
str_to_num<T> (ipos(), &ilast, m_Base, v);
|
||||
} while (ilast == end() && underflow());
|
||||
skip (distance (ipos(), ilast));
|
||||
}
|
||||
|
||||
void istringstream::iread (int32_t& v) { read_number (v); }
|
||||
void istringstream::iread (double& v) { read_number (v); }
|
||||
#if HAVE_INT64_T
|
||||
void istringstream::iread (int64_t& v) { read_number (v); }
|
||||
#endif
|
||||
#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
|
||||
void istringstream::iread (long long& v) { read_number (v); }
|
||||
#endif
|
||||
|
||||
void istringstream::iread (wchar_t& v)
|
||||
{
|
||||
if ((v = skip_delimiters()) == wchar_t(m_Delimiters[0]))
|
||||
return;
|
||||
size_t cs = Utf8SequenceBytes (v) - 1;
|
||||
if (remaining() >= cs || underflow(cs) >= cs) {
|
||||
ungetc();
|
||||
v = *utf8in (ipos());
|
||||
skip (cs + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void istringstream::iread (bool& v)
|
||||
{
|
||||
static const char tf[2][8] = { "false", "true" };
|
||||
char c = skip_delimiters();
|
||||
v = (c == 't' || c == '1');
|
||||
if (c != tf[v][0])
|
||||
return;
|
||||
for (const char* tv = tf[v]; c == *tv && (remaining() || underflow()); ++tv)
|
||||
istream::iread (c);
|
||||
ungetc();
|
||||
}
|
||||
|
||||
void istringstream::iread (string& v)
|
||||
{
|
||||
v.clear();
|
||||
char prevc, quoteChar = 0, c = skip_delimiters();
|
||||
if (c == '\"' || c == '\'')
|
||||
quoteChar = c;
|
||||
else
|
||||
v += c;
|
||||
while (remaining() || underflow()) {
|
||||
prevc = c;
|
||||
istream::iread (c);
|
||||
if (!quoteChar && is_delimiter(c))
|
||||
break;
|
||||
if (prevc == '\\') {
|
||||
switch (c) {
|
||||
case 't': c = '\t'; break;
|
||||
case 'n': c = '\n'; break;
|
||||
case 'r': c = '\r'; break;
|
||||
case 'b': c = '\b'; break;
|
||||
case 'E': c = 27; break; // ESC sequence
|
||||
case '\"': c = '\"'; break;
|
||||
case '\'': c = '\''; break;
|
||||
case '\\': c = '\\'; break;
|
||||
};
|
||||
v.end()[-1] = c;
|
||||
} else {
|
||||
if (c == quoteChar)
|
||||
break;
|
||||
v += c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void istringstream::read (void* buffer, size_type sz)
|
||||
{
|
||||
if (remaining() < sz && underflow(sz) < sz)
|
||||
#ifdef WANT_STREAM_BOUNDS_CHECKING
|
||||
verify_remaining ("read", "", sz);
|
||||
#else
|
||||
assert (remaining() >= size());
|
||||
#endif
|
||||
istream::read (buffer, sz);
|
||||
}
|
||||
|
||||
void istringstream::read (memlink& buf)
|
||||
{
|
||||
if (remaining() < buf.size() && underflow(buf.size()) < buf.size())
|
||||
#ifdef WANT_STREAM_BOUNDS_CHECKING
|
||||
verify_remaining ("read", "", buf.size());
|
||||
#else
|
||||
assert (remaining() >= buf.size());
|
||||
#endif
|
||||
istream::read (buf);
|
||||
}
|
||||
|
||||
/// Reads one character from the stream.
|
||||
int istringstream::get (void)
|
||||
{
|
||||
int8_t v = 0;
|
||||
if (remaining() || underflow())
|
||||
istream::iread (v);
|
||||
return (v);
|
||||
}
|
||||
|
||||
/// Reads characters into \p s until \p delim is found (but not stored or extracted)
|
||||
void istringstream::get (string& s, char delim)
|
||||
{
|
||||
getline (s, delim);
|
||||
if (!s.empty() && pos() > 0 && ipos()[-1] == delim)
|
||||
ungetc();
|
||||
}
|
||||
|
||||
/// Reads characters into \p p,n until \p delim is found (but not stored or extracted)
|
||||
void istringstream::get (char* p, size_type n, char delim)
|
||||
{
|
||||
assert (p && !n && "A non-empty buffer is required by this implementation");
|
||||
string s;
|
||||
get (s, delim);
|
||||
const size_t ntc (min (n - 1, s.size()));
|
||||
memcpy (p, s.data(), ntc);
|
||||
p[ntc] = 0;
|
||||
}
|
||||
|
||||
/// Reads characters into \p s until \p delim is extracted (but not stored)
|
||||
void istringstream::getline (string& s, char delim)
|
||||
{
|
||||
char oldDelim [VectorSize(m_Delimiters)];
|
||||
copy (VectorRange (m_Delimiters), oldDelim);
|
||||
fill (VectorRange (m_Delimiters), '\0');
|
||||
m_Delimiters[0] = delim;
|
||||
iread (s);
|
||||
copy (VectorRange (oldDelim), m_Delimiters);
|
||||
}
|
||||
|
||||
/// Reads characters into \p p,n until \p delim is extracted (but not stored)
|
||||
void istringstream::getline (char* p, size_type n, char delim)
|
||||
{
|
||||
assert (p && !n && "A non-empty buffer is required by this implementation");
|
||||
string s;
|
||||
getline (s, delim);
|
||||
const size_t ntc (min (n - 1, s.size()));
|
||||
memcpy (p, s.data(), ntc);
|
||||
p[ntc] = 0;
|
||||
}
|
||||
|
||||
/// Extract until \p delim or \p n chars have been read.
|
||||
void istringstream::ignore (size_type n, char delim)
|
||||
{
|
||||
while (n-- && (remaining() || underflow()) && get() != delim);
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// sistream.h
|
||||
//
|
||||
|
||||
#ifndef SISTREAM_H_0CCA102229A49F5D65EE852E62B27CE2
|
||||
#define SISTREAM_H_0CCA102229A49F5D65EE852E62B27CE2
|
||||
|
||||
#include "mistream.h"
|
||||
#include "uassert.h"
|
||||
#include "ustring.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// \class istringstream sistream.h ustl.h
|
||||
/// \ingroup TextStreams
|
||||
///
|
||||
/// \brief A stream that reads textual data from a memory block.
|
||||
///
|
||||
class istringstream : public istream {
|
||||
public:
|
||||
static const size_type c_MaxDelimiters = 16; ///< Maximum number of word delimiters.
|
||||
public:
|
||||
istringstream (void);
|
||||
istringstream (const void* p, size_type n);
|
||||
explicit istringstream (const cmemlink& source);
|
||||
void iread (int8_t& v);
|
||||
void iread (int32_t& v);
|
||||
void iread (double& v);
|
||||
void iread (bool& v);
|
||||
void iread (wchar_t& v);
|
||||
void iread (string& v);
|
||||
#ifdef HAVE_INT64_T
|
||||
void iread (int64_t& v);
|
||||
#endif
|
||||
#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
|
||||
void iread (long long& v);
|
||||
#endif
|
||||
inline string str (void) const { string s; s.link (*this); return (s); }
|
||||
inline void str (const string& s) { link (s); }
|
||||
int get (void);
|
||||
inline void get (char& c) { c = get(); }
|
||||
void get (char* p, size_type n, char delim = '\n');
|
||||
void get (string& s, char delim = '\n');
|
||||
void getline (char* p, size_type n, char delim = '\n');
|
||||
void getline (string& s, char delim = '\n');
|
||||
void ignore (size_type n, char delim = '\0');
|
||||
inline char peek (void) { int8_t v; iread (v); ungetc(); return (v); }
|
||||
inline void putback (char) { ungetc(); }
|
||||
inline void unget (void) { ungetc(); }
|
||||
void set_delimiters (const char* delimiters);
|
||||
inline void set_base (short base);
|
||||
inline void set_decimal_separator (char) { }
|
||||
inline void set_thousand_separator (char) { }
|
||||
void read (void* buffer, size_type size);
|
||||
void read (memlink& buf);
|
||||
inline void read_strz (string& str);
|
||||
inline void sync (void) { skip (remaining()); }
|
||||
protected:
|
||||
char skip_delimiters (void);
|
||||
private:
|
||||
inline bool is_delimiter (char c) const;
|
||||
template <typename T> void read_number (T& v);
|
||||
private:
|
||||
char m_Delimiters [c_MaxDelimiters];
|
||||
uint8_t m_Base;
|
||||
};
|
||||
|
||||
/// Sets the numeric base used to read numbers.
|
||||
inline void istringstream::set_base (short base)
|
||||
{
|
||||
m_Base = base;
|
||||
}
|
||||
|
||||
/// Reads a null-terminated character stream. This is not allowed in this class.
|
||||
inline void istringstream::read_strz (string&)
|
||||
{
|
||||
assert (!"Reading nul characters is not allowed from text streams");
|
||||
}
|
||||
|
||||
/// Reads one type as another.
|
||||
template <typename RealT, typename CastT>
|
||||
inline void _cast_read (istringstream& is, RealT& v)
|
||||
{
|
||||
CastT cv;
|
||||
is.iread (cv);
|
||||
v = RealT (cv);
|
||||
}
|
||||
|
||||
inline istringstream& operator>> (istringstream& is, int8_t& v) { is.iread (v); return (is); }
|
||||
inline istringstream& operator>> (istringstream& is, int32_t& v){ is.iread (v); return (is); }
|
||||
inline istringstream& operator>> (istringstream& is, double& v) { is.iread (v); return (is); }
|
||||
inline istringstream& operator>> (istringstream& is, bool& v) { is.iread (v); return (is); }
|
||||
inline istringstream& operator>> (istringstream& is, wchar_t& v){ is.iread (v); return (is); }
|
||||
inline istringstream& operator>> (istringstream& is, string& v) { is.iread (v); return (is); }
|
||||
#if HAVE_INT64_T
|
||||
inline istringstream& operator>> (istringstream& is, int64_t& v){ is.iread (v); return (is); }
|
||||
#endif
|
||||
#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
|
||||
inline istringstream& operator>> (istringstream& is, long long& v) { is.iread (v); return (is); }
|
||||
#endif
|
||||
|
||||
#define ISTRSTREAM_CAST_OPERATOR(RealT, CastT) \
|
||||
inline istringstream& operator>> (istringstream& is, RealT& v) \
|
||||
{ _cast_read<RealT,CastT>(is, v); return (is); }
|
||||
|
||||
ISTRSTREAM_CAST_OPERATOR (uint8_t, int8_t)
|
||||
ISTRSTREAM_CAST_OPERATOR (int16_t, int32_t)
|
||||
ISTRSTREAM_CAST_OPERATOR (uint16_t, int32_t)
|
||||
ISTRSTREAM_CAST_OPERATOR (uint32_t, int32_t)
|
||||
ISTRSTREAM_CAST_OPERATOR (float, double)
|
||||
#if HAVE_THREE_CHAR_TYPES
|
||||
ISTRSTREAM_CAST_OPERATOR (char, int8_t)
|
||||
#endif
|
||||
#if HAVE_INT64_T
|
||||
ISTRSTREAM_CAST_OPERATOR (uint64_t, int64_t)
|
||||
#endif
|
||||
#if SIZE_OF_LONG == SIZE_OF_INT
|
||||
ISTRSTREAM_CAST_OPERATOR (long, int)
|
||||
ISTRSTREAM_CAST_OPERATOR (unsigned long,int)
|
||||
#endif
|
||||
#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
|
||||
ISTRSTREAM_CAST_OPERATOR (unsigned long long, long long)
|
||||
#endif
|
||||
#undef ISTRSTREAM_CAST_OPERATOR
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// sostream.h
|
||||
//
|
||||
|
||||
#include "mistream.h" // for istream_iterator, referenced in utf8.h
|
||||
#include "sostream.h"
|
||||
#include "uassert.h"
|
||||
#include "ulimits.h"
|
||||
#include "ustring.h"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// Creates an output string stream linked to the given memory area.
|
||||
ostringstream::ostringstream (void* p, size_t n)
|
||||
: ostream (),
|
||||
m_Buffer (),
|
||||
m_Flags (0),
|
||||
m_Width (0),
|
||||
m_Base (10),
|
||||
m_Precision (2)
|
||||
{
|
||||
link (p, n);
|
||||
}
|
||||
|
||||
/// Creates an output string stream, initializing the buffer with v.
|
||||
ostringstream::ostringstream (const string& v)
|
||||
: ostream (),
|
||||
m_Buffer (v),
|
||||
m_Flags (0),
|
||||
m_Width (0),
|
||||
m_Base (10),
|
||||
m_Precision (2)
|
||||
{
|
||||
ostream::link (m_Buffer);
|
||||
}
|
||||
|
||||
/// Copies \p s to the internal buffer.
|
||||
void ostringstream::str (const string& s)
|
||||
{
|
||||
m_Buffer = s;
|
||||
ostream::link (m_Buffer);
|
||||
SetPos (m_Buffer.size());
|
||||
}
|
||||
|
||||
/// Writes a single character into the stream.
|
||||
void ostringstream::iwrite (uint8_t v)
|
||||
{
|
||||
if (remaining() >= 1 || overflow() >= 1)
|
||||
ostream::iwrite (v);
|
||||
}
|
||||
|
||||
/// Writes \p buf of size \p bufSize through the internal buffer.
|
||||
void ostringstream::write_buffer (const char* buf, size_type bufSize)
|
||||
{
|
||||
size_type btw = 0, written = 0;
|
||||
while ((written += btw) < bufSize && (remaining() || overflow(bufSize - written)))
|
||||
write (buf + written, btw = min (remaining(), bufSize - written));
|
||||
}
|
||||
|
||||
/// Simple decimal encoding of \p n into \p fmt.
|
||||
inline char* ostringstream::encode_dec (char* fmt, uint32_t n) const
|
||||
{
|
||||
do {
|
||||
*fmt++ = '0' + n % 10;
|
||||
} while (n /= 10);
|
||||
return (fmt);
|
||||
}
|
||||
|
||||
/// Generates a sprintf format string for the given type.
|
||||
void ostringstream::fmtstring (char* fmt, const char* typestr, bool bInteger) const
|
||||
{
|
||||
*fmt++ = '%';
|
||||
if (m_Width)
|
||||
fmt = encode_dec (fmt, m_Width);
|
||||
if (m_Flags & left)
|
||||
*fmt++ = '-';
|
||||
if (!bInteger) {
|
||||
*fmt++ = '.';
|
||||
fmt = encode_dec (fmt, m_Precision);
|
||||
}
|
||||
while (*typestr)
|
||||
*fmt++ = *typestr++;
|
||||
if (bInteger) {
|
||||
if (m_Base == 16)
|
||||
fmt[-1] = 'X';
|
||||
else if (m_Base == 8)
|
||||
fmt[-1] = 'o';
|
||||
} else {
|
||||
if (m_Flags & scientific)
|
||||
fmt[-1] = 'E';
|
||||
}
|
||||
*fmt = 0;
|
||||
}
|
||||
|
||||
/// Writes \p v into the stream as utf8
|
||||
void ostringstream::iwrite (wchar_t v)
|
||||
{
|
||||
char buffer [8];
|
||||
*utf8out(buffer) = v;
|
||||
write_buffer (buffer, Utf8Bytes(v));
|
||||
}
|
||||
|
||||
/// Writes value \p v into the stream as text.
|
||||
void ostringstream::iwrite (bool v)
|
||||
{
|
||||
static const char tf[2][8] = { "false", "true" };
|
||||
write_buffer (tf[v], 5 - v);
|
||||
}
|
||||
|
||||
/// Equivalent to a vsprintf on the string.
|
||||
int ostringstream::vformat (const char* fmt, va_list args)
|
||||
{
|
||||
#if HAVE_VA_COPY
|
||||
va_list args2;
|
||||
#else
|
||||
#define args2 args
|
||||
#undef __va_copy
|
||||
#define __va_copy(x,y)
|
||||
#endif
|
||||
size_t rv, space;
|
||||
do {
|
||||
space = remaining();
|
||||
__va_copy (args2, args);
|
||||
rv = vsnprintf (ipos(), space, fmt, args2);
|
||||
if (ssize_t(rv) < 0)
|
||||
rv = space;
|
||||
} while (rv >= space && rv < overflow(rv + 1));
|
||||
SetPos (pos() + min (rv, space));
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/// Equivalent to a sprintf on the string.
|
||||
int ostringstream::format (const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, fmt);
|
||||
const int rv = vformat (fmt, args);
|
||||
va_end (args);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/// Links to string \p l as resizable.
|
||||
void ostringstream::link (void* p, size_t n)
|
||||
{
|
||||
assert ((p || !n) && "The output string buffer must not be read-only");
|
||||
ostream::link (p, n);
|
||||
m_Buffer.link (p, n);
|
||||
}
|
||||
|
||||
/// Writes the contents of \p buffer of \p size into the stream.
|
||||
void ostringstream::write (const void* buffer, size_type sz)
|
||||
{
|
||||
if (remaining() < sz && overflow(sz) < sz)
|
||||
return;
|
||||
ostream::write (buffer, sz);
|
||||
}
|
||||
|
||||
/// Writes the contents of \p buf into the stream.
|
||||
void ostringstream::write (const cmemlink& buf)
|
||||
{
|
||||
if (remaining() < buf.size() && overflow(buf.size()) < buf.size())
|
||||
return;
|
||||
ostream::write (buf);
|
||||
}
|
||||
|
||||
/// Flushes the internal buffer by truncating it at the current position.
|
||||
void ostringstream::flush (void)
|
||||
{
|
||||
m_Buffer.resize (pos());
|
||||
}
|
||||
|
||||
/// Attempts to create more output space. Returns remaining().
|
||||
ostringstream::size_type ostringstream::overflow (size_type n)
|
||||
{
|
||||
if (n > remaining()) {
|
||||
const uoff_t oldPos (pos());
|
||||
m_Buffer.reserve (oldPos + n, false);
|
||||
m_Buffer.resize (oldPos + n);
|
||||
ostream::link (m_Buffer);
|
||||
SetPos (oldPos);
|
||||
}
|
||||
verify_remaining ("write", "text", n);
|
||||
return (remaining());
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// sostream.h
|
||||
//
|
||||
|
||||
#ifndef SOSTREAM_H_5323DC8C26E181D43278F2F53FDCF19F
|
||||
#define SOSTREAM_H_5323DC8C26E181D43278F2F53FDCF19F
|
||||
|
||||
#include "uassert.h"
|
||||
#include "ustring.h"
|
||||
#include "mostream.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
class string;
|
||||
|
||||
/// \class ostringstream sostream.h ustl.h
|
||||
/// \ingroup TextStreams
|
||||
///
|
||||
/// \brief This stream writes textual data into a memory block.
|
||||
///
|
||||
class ostringstream : public ostream {
|
||||
public:
|
||||
ostringstream (const string& v = string::empty_string);
|
||||
ostringstream (void* p, size_t n);
|
||||
void iwrite (uint8_t v);
|
||||
void iwrite (wchar_t v);
|
||||
inline void iwrite (int v) { iformat (v); }
|
||||
inline void iwrite (unsigned int v) { iformat (v); }
|
||||
inline void iwrite (long int v) { iformat (v); }
|
||||
inline void iwrite (unsigned long int v) { iformat (v); }
|
||||
inline void iwrite (float v) { iformat (v); }
|
||||
inline void iwrite (double v) { iformat (v); }
|
||||
void iwrite (bool v);
|
||||
inline void iwrite (const char* s) { write_buffer (s, strlen(s)); }
|
||||
inline void iwrite (const string& v) { write_buffer (v.begin(), v.size()); }
|
||||
inline void iwrite (fmtflags f);
|
||||
#if HAVE_LONG_LONG
|
||||
inline void iwrite (long long v) { iformat (v); }
|
||||
inline void iwrite (unsigned long long v) { iformat (v); }
|
||||
#endif
|
||||
inline size_type max_size (void) const { return (m_Buffer.max_size()); }
|
||||
inline void put (char c) { iwrite (uint8_t(c)); }
|
||||
int vformat (const char* fmt, va_list args);
|
||||
int format (const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3)));
|
||||
inline void set_base (uint16_t b) { m_Base = b; }
|
||||
inline void set_width (uint16_t w) { m_Width = w; }
|
||||
inline void set_decimal_separator (char) { }
|
||||
inline void set_thousand_separator (char) { }
|
||||
inline void set_precision (uint16_t v) { m_Precision = v; }
|
||||
void link (void* p, size_type n);
|
||||
inline void link (memlink& l) { link (l.data(), l.writable_size()); }
|
||||
inline const string& str (void) { flush(); return (m_Buffer); }
|
||||
void str (const string& s);
|
||||
void write (const void* buffer, size_type size);
|
||||
void write (const cmemlink& buf);
|
||||
inline void write_strz (const char*) { assert (!"Writing nul characters into a text stream is not allowed"); }
|
||||
void flush (void);
|
||||
virtual size_type overflow (size_type n = 1);
|
||||
protected:
|
||||
void write_buffer (const char* buf, size_type bufSize);
|
||||
inline void reserve (size_type n) { m_Buffer.reserve (n, false); }
|
||||
inline size_type capacity (void) const { return (m_Buffer.capacity()); }
|
||||
private:
|
||||
inline char* encode_dec (char* fmt, uint32_t n) const;
|
||||
void fmtstring (char* fmt, const char* typestr, bool bInteger) const;
|
||||
template <typename T>
|
||||
void iformat (T v);
|
||||
private:
|
||||
string m_Buffer; ///< The output buffer.
|
||||
uint32_t m_Flags; ///< See ios_base::fmtflags.
|
||||
uint16_t m_Width; ///< Field width.
|
||||
uint8_t m_Base; ///< Numeric base for writing numbers.
|
||||
uint8_t m_Precision; ///< Number of digits after the decimal separator.
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
inline const char* printf_typestring (const T&) { return (""); }
|
||||
#define PRINTF_TYPESTRING_SPEC(type,str) \
|
||||
template <> inline const char* printf_typestring (const type&) { return (str); }
|
||||
PRINTF_TYPESTRING_SPEC (int, "d")
|
||||
PRINTF_TYPESTRING_SPEC (unsigned int, "u")
|
||||
PRINTF_TYPESTRING_SPEC (long, "ld")
|
||||
PRINTF_TYPESTRING_SPEC (unsigned long, "lu")
|
||||
PRINTF_TYPESTRING_SPEC (float, "f")
|
||||
PRINTF_TYPESTRING_SPEC (double, "lf")
|
||||
#if HAVE_LONG_LONG
|
||||
PRINTF_TYPESTRING_SPEC (long long, "lld")
|
||||
PRINTF_TYPESTRING_SPEC (unsigned long long, "llu")
|
||||
#endif
|
||||
#undef PRINTF_TYPESTRING_SPEC
|
||||
|
||||
template <typename T>
|
||||
void ostringstream::iformat (T v)
|
||||
{
|
||||
char fmt [16];
|
||||
fmtstring (fmt, printf_typestring(v), numeric_limits<T>::is_integer);
|
||||
format (fmt, v);
|
||||
}
|
||||
|
||||
/// Sets the flag \p f in the stream.
|
||||
inline void ostringstream::iwrite (fmtflags f)
|
||||
{
|
||||
switch (f) {
|
||||
case oct: set_base (8); break;
|
||||
case dec: set_base (10); break;
|
||||
case hex: set_base (16); break;
|
||||
case left: m_Flags |= left; m_Flags &= ~right; break;
|
||||
case right: m_Flags |= right; m_Flags &= ~left; break;
|
||||
default: m_Flags |= f; break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#define OSTRSTREAM_OPERATOR(RealT, CastT) \
|
||||
inline ostringstream& operator<< (ostringstream& os, RealT v) \
|
||||
{ os.iwrite ((CastT) v); return (os); }
|
||||
|
||||
template <typename T>
|
||||
OSTRSTREAM_OPERATOR (T*, unsigned long int)
|
||||
OSTRSTREAM_OPERATOR (const void*, unsigned long int)
|
||||
OSTRSTREAM_OPERATOR (void*, unsigned long int)
|
||||
OSTRSTREAM_OPERATOR (const char*, const char*)
|
||||
OSTRSTREAM_OPERATOR (char*, const char*)
|
||||
OSTRSTREAM_OPERATOR (uint8_t*, const char*)
|
||||
OSTRSTREAM_OPERATOR (const uint8_t*, const char*)
|
||||
OSTRSTREAM_OPERATOR (const string&, const string&)
|
||||
OSTRSTREAM_OPERATOR (ios_base::fmtflags,ios_base::fmtflags)
|
||||
OSTRSTREAM_OPERATOR (int8_t, uint8_t)
|
||||
OSTRSTREAM_OPERATOR (uint8_t, uint8_t)
|
||||
OSTRSTREAM_OPERATOR (short int, int)
|
||||
OSTRSTREAM_OPERATOR (unsigned short, unsigned int)
|
||||
OSTRSTREAM_OPERATOR (int, int)
|
||||
OSTRSTREAM_OPERATOR (unsigned int, unsigned int)
|
||||
OSTRSTREAM_OPERATOR (long, long)
|
||||
OSTRSTREAM_OPERATOR (unsigned long, unsigned long)
|
||||
OSTRSTREAM_OPERATOR (float, float)
|
||||
OSTRSTREAM_OPERATOR (double, double)
|
||||
OSTRSTREAM_OPERATOR (bool, bool)
|
||||
OSTRSTREAM_OPERATOR (wchar_t, wchar_t)
|
||||
#if HAVE_THREE_CHAR_TYPES
|
||||
OSTRSTREAM_OPERATOR (char, uint8_t)
|
||||
#endif
|
||||
#if HAVE_LONG_LONG
|
||||
OSTRSTREAM_OPERATOR (long long, long long)
|
||||
OSTRSTREAM_OPERATOR (unsigned long long, unsigned long long)
|
||||
#endif
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
/// \file strmsize.h
|
||||
/// \brief This file contains stream_size_of functions for basic types and *STREAMABLE macros.
|
||||
/// stream_size_of functions return the size of the object's data that is written or
|
||||
/// read from a stream.
|
||||
//
|
||||
|
||||
#ifndef STRMSIZE_H_052FF16B2D8A608761BF10333D065073
|
||||
#define STRMSIZE_H_052FF16B2D8A608761BF10333D065073
|
||||
|
||||
#include "uassert.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// Returns the size of the given object. Overloads for standard types are available.
|
||||
template <typename T>
|
||||
inline size_t stream_size_of (T*) { return (sizeof(T*)); }
|
||||
#ifndef DOXYGEN_SHOULD_IGNORE_THIS
|
||||
inline size_t stream_size_of (int8_t) { return (sizeof(int8_t)); }
|
||||
inline size_t stream_size_of (uint8_t) { return (sizeof(uint8_t)); }
|
||||
inline size_t stream_size_of (int16_t) { return (sizeof(int16_t)); }
|
||||
inline size_t stream_size_of (uint16_t) { return (sizeof(uint16_t)); }
|
||||
inline size_t stream_size_of (int32_t) { return (sizeof(int32_t)); }
|
||||
inline size_t stream_size_of (uint32_t) { return (sizeof(uint32_t)); }
|
||||
inline size_t stream_size_of (float) { return (sizeof(float)); }
|
||||
inline size_t stream_size_of (double) { return (sizeof(double)); }
|
||||
inline size_t stream_size_of (bool) { return (sizeof(uint8_t)); }
|
||||
inline size_t stream_size_of (wchar_t) { return (sizeof(wchar_t)); }
|
||||
#if HAVE_THREE_CHAR_TYPES
|
||||
inline size_t stream_size_of (char) { return (sizeof(char)); }
|
||||
#endif
|
||||
#if HAVE_INT64_T
|
||||
inline size_t stream_size_of (int64_t) { return (sizeof(int64_t)); }
|
||||
inline size_t stream_size_of (uint64_t) { return (sizeof(uint64_t)); }
|
||||
#endif
|
||||
#if SIZE_OF_LONG == SIZE_OF_INT
|
||||
inline size_t stream_size_of (long v) { return (sizeof (v)); }
|
||||
inline size_t stream_size_of (unsigned long v) { return (sizeof (v)); }
|
||||
#endif
|
||||
#if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
|
||||
inline size_t stream_size_of (long long v) { return (sizeof (v)); }
|
||||
inline size_t stream_size_of (unsigned long long v) { return (sizeof (v)); }
|
||||
#endif
|
||||
#endif // DOXYGEN_SHOULD_IGNORE_THIS
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
/// Declares that T is not written to istream/ostream.
|
||||
#define NOT_STREAMABLE(T) \
|
||||
namespace ustl { \
|
||||
inline istream& operator>> (istream& is, T&) { return (is); } \
|
||||
inline ostream& operator<< (ostream& os, const T&) { return (os); } \
|
||||
inline size_t stream_size_of (const T&) { return (0); } \
|
||||
}
|
||||
|
||||
//
|
||||
// Extra overloads in this macro are needed because it is the one used for
|
||||
// marshalling pointers. Passing a pointer to stream_size_of creates a
|
||||
// conversion ambiguity between converting to const pointer& and converting
|
||||
// to bool; the compiler always chooses the bool conversion (because it
|
||||
// requires 1 conversion instead of 2 for the other choice). There is little
|
||||
// point in adding the overloads to other macros, since they are never used
|
||||
// for pointers.
|
||||
//
|
||||
/// Declares that T is to be written as is into binary streams.
|
||||
#define INTEGRAL_STREAMABLE(T) \
|
||||
namespace ustl { \
|
||||
inline istream& operator>> (istream& is, T& v) { is.iread(v); return (is); } \
|
||||
inline ostream& operator<< (ostream& os, const T& v) { os.iwrite(v); return (os); } \
|
||||
inline ostream& operator<< (ostream& os, T& v) { os.iwrite(v); return (os); } \
|
||||
inline size_t stream_size_of (const T& v) { return (sizeof(v)); } \
|
||||
inline size_t stream_size_of (T& v) { return (sizeof(v)); } \
|
||||
}
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define STD_STREAMABLE_SZCHK_BEGIN
|
||||
#define STD_STREAMABLE_SZCHK_END
|
||||
#else
|
||||
#define STD_STREAMABLE_SZCHK_BEGIN \
|
||||
assert (os.aligned (alignof (v))); \
|
||||
const uoff_t vStart (os.pos())
|
||||
#define STD_STREAMABLE_SZCHK_END \
|
||||
if (os.pos() - vStart != v.stream_size()) \
|
||||
throw stream_bounds_exception ("write", typeid(v).name(), vStart, os.pos() - vStart, v.stream_size())
|
||||
#endif
|
||||
|
||||
/// Declares that T contains read, write, and stream_size methods.
|
||||
#define STD_STREAMABLE(T) \
|
||||
namespace ustl { \
|
||||
inline istream& operator>> (istream& is, T& v) { assert (is.aligned (alignof (v))); v.read (is); return (is); } \
|
||||
inline ostream& operator<< (ostream& os, const T& v) { STD_STREAMABLE_SZCHK_BEGIN; v.write (os); STD_STREAMABLE_SZCHK_END; return (os); } \
|
||||
inline size_t stream_size_of (const T& v) { return (v.stream_size()); } \
|
||||
}
|
||||
|
||||
/// Declares that T is to be cast into TSUB for streaming.
|
||||
#define CAST_STREAMABLE(T,TSUB) \
|
||||
namespace ustl { \
|
||||
inline istream& operator>> (istream& is, T& v) { TSUB sv; is >> sv; v = (T)(sv); return (is); } \
|
||||
inline ostream& operator<< (ostream& os, const T& v) { os << TSUB(v); return (os); } \
|
||||
inline size_t stream_size_of (const T& v) { return (sizeof(TSUB(v))); } \
|
||||
}
|
||||
|
||||
/// Placed into a class it declares the methods required by STD_STREAMABLE. Syntactic sugar.
|
||||
#define DECLARE_STD_STREAMABLE \
|
||||
public: \
|
||||
void read (istream& is); \
|
||||
void write (ostream& os) const; \
|
||||
size_t stream_size (void) const
|
||||
|
||||
/// Declares \p T to be writable to text streams. Reading is not implemented because you should not do it.
|
||||
#define TEXT_STREAMABLE(T) \
|
||||
namespace ustl { \
|
||||
inline ostringstream& operator<< (ostringstream& os, const T& v) \
|
||||
{ v.text_write (os); return (os); } \
|
||||
}
|
||||
|
||||
/// Specifies that \p T is printed by using it as an index into \p Names string array.
|
||||
#define LOOKUP_TEXT_STREAMABLE(T,Names,nNames) \
|
||||
namespace ustl { \
|
||||
inline ostringstream& operator<< (ostringstream& os, const T& v) \
|
||||
{ \
|
||||
if (uoff_t(v) < (nNames)) \
|
||||
os << Names[v]; \
|
||||
else \
|
||||
os << uoff_t(v); \
|
||||
return (os); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,677 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// ualgo.h
|
||||
//
|
||||
// Implementation of STL algorithms.
|
||||
//
|
||||
// The function prototypes are copied
|
||||
// exactly from the SGI version of STL documentation along with comments about
|
||||
// their use. The code is NOT the same, though the functionality usually is.
|
||||
//
|
||||
|
||||
#ifndef UALGO_H_711AB4214D417A51166694D47A662D6E
|
||||
#define UALGO_H_711AB4214D417A51166694D47A662D6E
|
||||
|
||||
#include "upair.h"
|
||||
#include "ualgobase.h"
|
||||
#include "ufunction.h"
|
||||
#include "upredalgo.h"
|
||||
#include "umemory.h"
|
||||
#include <stdlib.h> // for rand()
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// Swaps corresponding elements of [first, last) and [result,)
|
||||
/// \ingroup SwapAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator1, typename ForwardIterator2>
|
||||
inline ForwardIterator2 swap_ranges (ForwardIterator1 first, ForwardIterator2 last, ForwardIterator2 result)
|
||||
{
|
||||
for (; first != last; ++first, ++result)
|
||||
iter_swap (first, result);
|
||||
return (result);
|
||||
}
|
||||
|
||||
/// Returns the first iterator i in the range [first, last) such that
|
||||
/// *i == value. Returns last if no such iterator exists.
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename InputIterator, typename EqualityComparable>
|
||||
inline InputIterator find (InputIterator first, InputIterator last, const EqualityComparable& value)
|
||||
{
|
||||
while (first != last && !(*first == value))
|
||||
++ first;
|
||||
return (first);
|
||||
}
|
||||
|
||||
/// Returns the first iterator such that *i == *(i + 1)
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator>
|
||||
ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last)
|
||||
{
|
||||
if (first != last)
|
||||
for (ForwardIterator prev = first; ++first != last; ++ prev)
|
||||
if (*prev == *first)
|
||||
return (prev);
|
||||
return (last);
|
||||
}
|
||||
|
||||
/// Returns the pointer to the first pair of unequal elements.
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename InputIterator>
|
||||
pair<InputIterator,InputIterator>
|
||||
mismatch (InputIterator first1, InputIterator last1, InputIterator first2)
|
||||
{
|
||||
while (first1 != last1 && *first1 == *first2)
|
||||
++ first1, ++ first2;
|
||||
return (make_pair (first1, first2));
|
||||
}
|
||||
|
||||
/// \brief Returns true if two ranges are equal.
|
||||
/// This is an extension, present in uSTL and SGI STL.
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename InputIterator>
|
||||
inline bool equal (InputIterator first1, InputIterator last1, InputIterator first2)
|
||||
{
|
||||
return (mismatch (first1, last1, first2).first == last1);
|
||||
}
|
||||
|
||||
/// Count finds the number of elements in [first, last) that are equal
|
||||
/// to value. More precisely, the first version of count returns the
|
||||
/// number of iterators i in [first, last) such that *i == value.
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename InputIterator, typename EqualityComparable>
|
||||
inline size_t count (InputIterator first, InputIterator last, const EqualityComparable& value)
|
||||
{
|
||||
size_t total = 0;
|
||||
for (; first != last; ++first)
|
||||
if (*first == value)
|
||||
++ total;
|
||||
return (total);
|
||||
}
|
||||
|
||||
///
|
||||
/// The first version of transform performs the operation op(*i) for each
|
||||
/// iterator i in the range [first, last), and assigns the result of that
|
||||
/// operation to *o, where o is the corresponding output iterator. That is,
|
||||
/// for each n such that 0 <= n < last - first, it performs the assignment
|
||||
/// *(result + n) = op(*(first + n)).
|
||||
/// The return value is result + (last - first).
|
||||
/// \ingroup MutatingAlgorithms
|
||||
/// \ingroup PredicateAlgorithms
|
||||
///
|
||||
template <typename InputIterator, typename OutputIterator, typename UnaryFunction>
|
||||
inline OutputIterator transform (InputIterator first, InputIterator last, OutputIterator result, UnaryFunction op)
|
||||
{
|
||||
for (; first != last; ++result, ++first)
|
||||
*result = op (*first);
|
||||
return (result);
|
||||
}
|
||||
|
||||
///
|
||||
/// The second version of transform is very similar, except that it uses a
|
||||
/// Binary Function instead of a Unary Function: it performs the operation
|
||||
/// op(*i1, *i2) for each iterator i1 in the range [first1, last1) and assigns
|
||||
/// the result to *o, where i2 is the corresponding iterator in the second
|
||||
/// input range and where o is the corresponding output iterator. That is,
|
||||
/// for each n such that 0 <= n < last1 - first1, it performs the assignment
|
||||
/// *(result + n) = op(*(first1 + n), *(first2 + n).
|
||||
/// The return value is result + (last1 - first1).
|
||||
/// \ingroup MutatingAlgorithms
|
||||
/// \ingroup PredicateAlgorithms
|
||||
///
|
||||
template <typename InputIterator1, typename InputIterator2, typename OutputIterator, typename BinaryFunction>
|
||||
inline OutputIterator transform (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryFunction op)
|
||||
{
|
||||
for (; first1 != last1; ++result, ++first1, ++first2)
|
||||
*result = op (*first1, *first2);
|
||||
return (result);
|
||||
}
|
||||
|
||||
/// Replace replaces every element in the range [first, last) equal to
|
||||
/// old_value with new_value. That is: for every iterator i,
|
||||
/// if *i == old_value then it performs the assignment *i = new_value.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator, typename T>
|
||||
inline void replace (ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
if (*first == old_value)
|
||||
*first = new_value;
|
||||
}
|
||||
|
||||
/// Replace_copy copies elements from the range [first, last) to the range
|
||||
/// [result, result + (last-first)), except that any element equal to old_value
|
||||
/// is not copied; new_value is copied instead. More precisely, for every
|
||||
/// integer n such that 0 <= n < last-first, replace_copy performs the
|
||||
/// assignment *(result+n) = new_value if *(first+n) == old_value, and
|
||||
/// *(result+n) = *(first+n) otherwise.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename InputIterator, typename OutputIterator, typename T>
|
||||
inline OutputIterator replace_copy (InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value)
|
||||
{
|
||||
for (; first != last; ++result, ++first)
|
||||
*result = (*first == old_value) ? new_value : *first;
|
||||
}
|
||||
|
||||
/// Generate assigns the result of invoking gen, a function object that
|
||||
/// takes no arguments, to each element in the range [first, last).
|
||||
/// \ingroup GeneratorAlgorithms
|
||||
/// \ingroup PredicateAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator, typename Generator>
|
||||
inline void generate (ForwardIterator first, ForwardIterator last, Generator gen)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
*first = gen();
|
||||
}
|
||||
|
||||
/// Generate_n assigns the result of invoking gen, a function object that
|
||||
/// takes no arguments, to each element in the range [first, first+n).
|
||||
/// The return value is first + n.
|
||||
/// \ingroup GeneratorAlgorithms
|
||||
/// \ingroup PredicateAlgorithms
|
||||
///
|
||||
template <typename OutputIterator, typename Generator>
|
||||
inline OutputIterator generate_n (OutputIterator first, size_t n, Generator gen)
|
||||
{
|
||||
for (uoff_t i = 0; i != n; ++i, ++first)
|
||||
*first = gen();
|
||||
return (first);
|
||||
}
|
||||
|
||||
/// \brief Reverse reverses a range.
|
||||
/// That is: for every i such that 0 <= i <= (last - first) / 2),
|
||||
/// it exchanges *(first + i) and *(last - (i + 1)).
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename BidirectionalIterator>
|
||||
inline void reverse (BidirectionalIterator first, BidirectionalIterator last)
|
||||
{
|
||||
for (; distance (first, --last) > 0; ++first)
|
||||
iter_swap (first, last);
|
||||
}
|
||||
|
||||
/// \brief Reverses [first,last) and writes it to \p output.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename BidirectionalIterator, typename OutputIterator>
|
||||
inline OutputIterator reverse_copy (BidirectionalIterator first, BidirectionalIterator last, OutputIterator result)
|
||||
{
|
||||
for (; first != last; ++result)
|
||||
*result = *--last;
|
||||
return (result);
|
||||
}
|
||||
|
||||
/// \brief Exchanges ranges [first, middle) and [middle, last)
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator>
|
||||
ForwardIterator rotate (ForwardIterator first, ForwardIterator middle, ForwardIterator last)
|
||||
{
|
||||
if (first == middle || middle == last)
|
||||
return (first);
|
||||
reverse (first, middle);
|
||||
reverse (middle, last);
|
||||
for (;first != middle && middle != last; ++first)
|
||||
iter_swap (first, --last);
|
||||
reverse (first, (first == middle ? last : middle));
|
||||
return (first);
|
||||
}
|
||||
|
||||
/// Specialization for pointers, which can be treated identically.
|
||||
template <typename T>
|
||||
inline T* rotate (T* first, T* middle, T* last)
|
||||
{
|
||||
rotate_fast (first, middle, last);
|
||||
return (first);
|
||||
}
|
||||
|
||||
|
||||
/// \brief Exchanges ranges [first, middle) and [middle, last) into \p result.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator, typename OutputIterator>
|
||||
inline OutputIterator rotate_copy (ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result)
|
||||
{
|
||||
return (copy (first, middle, copy (middle, last, result)));
|
||||
}
|
||||
|
||||
/// \brief Combines two sorted ranges.
|
||||
/// \ingroup SortingAlgorithms
|
||||
///
|
||||
template <typename InputIterator1, typename InputIterator2, typename OutputIterator>
|
||||
OutputIterator merge (InputIterator1 first1, InputIterator1 last1,
|
||||
InputIterator2 first2, InputIterator2 last2, OutputIterator result)
|
||||
{
|
||||
for (; first1 != last1 && first2 != last2; ++result) {
|
||||
if (*first1 < *first2)
|
||||
*result = *first1++;
|
||||
else
|
||||
*result = *first2++;
|
||||
}
|
||||
if (first1 < last1)
|
||||
return (copy (first1, last1, result));
|
||||
else
|
||||
return (copy (first2, last2, result));
|
||||
}
|
||||
|
||||
/// Combines two sorted ranges from the same container.
|
||||
/// \ingroup SortingAlgorithms
|
||||
///
|
||||
template <typename InputIterator>
|
||||
void inplace_merge (InputIterator first, InputIterator middle, InputIterator last)
|
||||
{
|
||||
for (; middle != last; ++first) {
|
||||
while (*first < *middle)
|
||||
++ first;
|
||||
reverse (first, middle);
|
||||
reverse (first, ++middle);
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove_copy copies elements that are not equal to value from the range
|
||||
/// [first, last) to a range beginning at result. The return value is the
|
||||
/// end of the resulting range. This operation is stable, meaning that the
|
||||
/// relative order of the elements that are copied is the same as in the
|
||||
/// range [first, last).
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename InputIterator, typename OutputIterator, typename T>
|
||||
OutputIterator remove_copy (InputIterator first, InputIterator last, OutputIterator result, const T& value)
|
||||
{
|
||||
for (; first != last; ++first) {
|
||||
if (!(*first == value)) {
|
||||
*result = *first;
|
||||
++ result;
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/// Remove_copy copies elements pointed to by iterators in [rfirst, rlast)
|
||||
/// from the range [first, last) to a range beginning at result. The return
|
||||
/// value is the end of the resulting range. This operation is stable, meaning
|
||||
/// that the relative order of the elements that are copied is the same as in the
|
||||
/// range [first, last). Range [rfirst, rlast) is assumed to be sorted.
|
||||
/// This algorithm is a uSTL extension.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename InputIterator, typename OutputIterator, typename RInputIterator>
|
||||
OutputIterator remove_copy (InputIterator first, InputIterator last, OutputIterator result, RInputIterator rfirst, RInputIterator rlast)
|
||||
{
|
||||
for (; first != last; ++first) {
|
||||
while (rfirst != rlast && *rfirst < first)
|
||||
++ rfirst;
|
||||
if (rfirst == rlast || first != *rfirst) {
|
||||
*result = *first;
|
||||
++ result;
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/// Remove removes from the range [first, last) all elements that are equal to
|
||||
/// value. That is, remove returns an iterator new_last such that the range
|
||||
/// [first, new_last) contains no elements equal to value. [1] The iterators
|
||||
/// in the range [new_last, last) are all still dereferenceable, but the
|
||||
/// elements that they point to are unspecified. Remove is stable, meaning
|
||||
/// that the relative order of elements that are not equal to value is
|
||||
/// unchanged.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator, typename T>
|
||||
inline ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& value)
|
||||
{
|
||||
return (remove_copy (first, last, first, value));
|
||||
}
|
||||
|
||||
/// Unique_copy copies elements from the range [first, last) to a range
|
||||
/// beginning with result, except that in a consecutive group of duplicate
|
||||
/// elements only the first one is copied. The return value is the end of
|
||||
/// the range to which the elements are copied. This behavior is similar
|
||||
/// to the Unix filter uniq.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
OutputIterator unique_copy (InputIterator first, InputIterator last, OutputIterator result)
|
||||
{
|
||||
if (first != last) {
|
||||
*result = *first;
|
||||
while (++first != last)
|
||||
if (!(*first == *result))
|
||||
*++result = *first;
|
||||
++ result;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/// Every time a consecutive group of duplicate elements appears in the range
|
||||
/// [first, last), the algorithm unique removes all but the first element.
|
||||
/// That is, unique returns an iterator new_last such that the range [first,
|
||||
/// new_last) contains no two consecutive elements that are duplicates.
|
||||
/// The iterators in the range [new_last, last) are all still dereferenceable,
|
||||
/// but the elements that they point to are unspecified. Unique is stable,
|
||||
/// meaning that the relative order of elements that are not removed is
|
||||
/// unchanged.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator>
|
||||
inline ForwardIterator unique (ForwardIterator first, ForwardIterator last)
|
||||
{
|
||||
return (unique_copy (first, last, first));
|
||||
}
|
||||
|
||||
/// Returns the furthermost iterator i in [first, last) such that,
|
||||
/// for every iterator j in [first, i), *j < value
|
||||
/// Assumes the range is sorted.
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator, typename LessThanComparable>
|
||||
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const LessThanComparable& value)
|
||||
{
|
||||
ForwardIterator mid;
|
||||
while (first != last) {
|
||||
mid = advance (first, distance (first,last) / 2);
|
||||
if (*mid < value)
|
||||
first = mid + 1;
|
||||
else
|
||||
last = mid;
|
||||
}
|
||||
return (first);
|
||||
}
|
||||
|
||||
/// Performs a binary search inside the sorted range.
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator, typename LessThanComparable>
|
||||
inline ForwardIterator binary_search (ForwardIterator first, ForwardIterator last, const LessThanComparable& value)
|
||||
{
|
||||
ForwardIterator found = lower_bound (first, last, value);
|
||||
return ((found == last || value < *found) ? last : found);
|
||||
}
|
||||
|
||||
/// Returns the furthermost iterator i in [first,last) such that for
|
||||
/// every iterator j in [first,i), value < *j is false.
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator, typename LessThanComparable>
|
||||
ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const LessThanComparable& value)
|
||||
{
|
||||
ForwardIterator mid;
|
||||
while (first != last) {
|
||||
mid = advance (first, distance (first,last) / 2);
|
||||
if (value < *mid)
|
||||
last = mid;
|
||||
else
|
||||
first = mid + 1;
|
||||
}
|
||||
return (last);
|
||||
}
|
||||
|
||||
/// Returns pair<lower_bound,upper_bound>
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator, typename LessThanComparable>
|
||||
inline pair<ForwardIterator,ForwardIterator> equal_range (ForwardIterator first, ForwardIterator last, const LessThanComparable& value)
|
||||
{
|
||||
pair<ForwardIterator,ForwardIterator> rv;
|
||||
rv.second = rv.first = lower_bound (first, last, value);
|
||||
while (rv.second != last && !(value < *(rv.second)))
|
||||
++ rv.second;
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/// Randomly permute the elements of the container.
|
||||
/// \ingroup GeneratorAlgorithms
|
||||
///
|
||||
template <typename RandomAccessIterator>
|
||||
void random_shuffle (RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
for (; first != last; ++ first)
|
||||
iter_swap (first, first + (rand() % distance (first, last)));
|
||||
}
|
||||
|
||||
/// \brief Generic compare function adaptor to pass to qsort
|
||||
/// \ingroup FunctorObjects
|
||||
template <typename ConstPointer, typename Compare>
|
||||
int qsort_adapter (const void* p1, const void* p2)
|
||||
{
|
||||
ConstPointer i1 = reinterpret_cast<ConstPointer>(p1);
|
||||
ConstPointer i2 = reinterpret_cast<ConstPointer>(p2);
|
||||
Compare comp;
|
||||
return (comp (*i1, *i2) ? -1 : (comp (*i2, *i1) ? 1 : 0));
|
||||
}
|
||||
|
||||
/// Sorts the container
|
||||
/// \ingroup SortingAlgorithms
|
||||
/// \ingroup PredicateAlgorithms
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare)
|
||||
{
|
||||
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
typedef typename iterator_traits<RandomAccessIterator>::const_pointer const_pointer;
|
||||
qsort (first, distance (first, last), sizeof(value_type),
|
||||
&qsort_adapter<const_pointer, Compare>);
|
||||
}
|
||||
|
||||
/// Sorts the container
|
||||
/// \ingroup SortingAlgorithms
|
||||
///
|
||||
template <typename RandomAccessIterator>
|
||||
inline void sort (RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
sort (first, last, less<value_type>());
|
||||
}
|
||||
|
||||
/// Sorts the container preserving order of equal elements.
|
||||
/// \ingroup SortingAlgorithms
|
||||
/// \ingroup PredicateAlgorithms
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
void stable_sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
|
||||
{
|
||||
for (RandomAccessIterator j, i = first; ++i < last;) { // Insertion sort
|
||||
for (j = i; j-- > first && !comp(*j, *i););
|
||||
rotate (++j, i, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sorts the container
|
||||
/// \ingroup SortingAlgorithms
|
||||
///
|
||||
template <typename RandomAccessIterator>
|
||||
inline void stable_sort (RandomAccessIterator first, RandomAccessIterator last)
|
||||
{
|
||||
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
stable_sort (first, last, less<value_type>());
|
||||
}
|
||||
|
||||
/// \brief Searches for the first subsequence [first2,last2) in [first1,last1)
|
||||
/// \ingroup SearchingAlgorithms
|
||||
template <typename ForwardIterator1, typename ForwardIterator2>
|
||||
inline ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2)
|
||||
{
|
||||
typedef typename iterator_traits<ForwardIterator1>::value_type value_type;
|
||||
return (search (first1, last1, first2, last2, equal_to<value_type>()));
|
||||
}
|
||||
|
||||
/// \brief Searches for the last subsequence [first2,last2) in [first1,last1)
|
||||
/// \ingroup SearchingAlgorithms
|
||||
template <typename ForwardIterator1, typename ForwardIterator2>
|
||||
inline ForwardIterator1 find_end (ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2)
|
||||
{
|
||||
typedef typename iterator_traits<ForwardIterator1>::value_type value_type;
|
||||
return (find_end (first1, last1, first2, last2, equal_to<value_type>()));
|
||||
}
|
||||
|
||||
/// \brief Searches for the first occurence of \p count \p values in [first, last)
|
||||
/// \ingroup SearchingAlgorithms
|
||||
template <typename Iterator, typename T>
|
||||
inline Iterator search_n (Iterator first, Iterator last, size_t count, const T& value)
|
||||
{
|
||||
typedef typename iterator_traits<Iterator>::value_type value_type;
|
||||
return (search_n (first, last, count, value, equal_to<value_type>()));
|
||||
}
|
||||
|
||||
/// \brief Searches [first1,last1) for the first occurrence of an element from [first2,last2)
|
||||
/// \ingroup SearchingAlgorithms
|
||||
template <typename InputIterator, typename ForwardIterator>
|
||||
inline InputIterator find_first_of (InputIterator first1, InputIterator last1, ForwardIterator first2, ForwardIterator last2)
|
||||
{
|
||||
typedef typename iterator_traits<InputIterator>::value_type value_type;
|
||||
return (find_first_of (first1, last1, first2, last2, equal_to<value_type>()));
|
||||
}
|
||||
|
||||
/// \brief Returns true if [first2,last2) is a subset of [first1,last1)
|
||||
/// \ingroup ConditionAlgorithms
|
||||
/// \ingroup SetAlgorithms
|
||||
template <typename InputIterator1, typename InputIterator2>
|
||||
inline bool includes (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)
|
||||
{
|
||||
typedef typename iterator_traits<InputIterator1>::value_type value_type;
|
||||
return (includes (first1, last1, first2, last2, less<value_type>()));
|
||||
}
|
||||
|
||||
/// \brief Merges [first1,last1) with [first2,last2)
|
||||
///
|
||||
/// Result will contain every element that is in either set. If duplicate
|
||||
/// elements are present, max(n,m) is placed in the result.
|
||||
///
|
||||
/// \ingroup SetAlgorithms
|
||||
template <typename InputIterator1, typename InputIterator2, typename OutputIterator>
|
||||
inline OutputIterator set_union (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)
|
||||
{
|
||||
typedef typename iterator_traits<InputIterator1>::value_type value_type;
|
||||
return (set_union (first1, last1, first2, last2, result, less<value_type>()));
|
||||
}
|
||||
|
||||
/// \brief Creates a set containing elements shared by the given ranges.
|
||||
/// \ingroup SetAlgorithms
|
||||
template <typename InputIterator1, typename InputIterator2, typename OutputIterator>
|
||||
inline OutputIterator set_intersection (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)
|
||||
{
|
||||
typedef typename iterator_traits<InputIterator1>::value_type value_type;
|
||||
return (set_intersection (first1, last1, first2, last2, result, less<value_type>()));
|
||||
}
|
||||
|
||||
/// \brief Removes from [first1,last1) elements present in [first2,last2)
|
||||
/// \ingroup SetAlgorithms
|
||||
template <typename InputIterator1, typename InputIterator2, typename OutputIterator>
|
||||
inline OutputIterator set_difference (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)
|
||||
{
|
||||
typedef typename iterator_traits<InputIterator1>::value_type value_type;
|
||||
return (set_difference (first1, last1, first2, last2, result, less<value_type>()));
|
||||
}
|
||||
|
||||
/// \brief Performs union of sets A-B and B-A.
|
||||
/// \ingroup SetAlgorithms
|
||||
template <typename InputIterator1, typename InputIterator2, typename OutputIterator>
|
||||
inline OutputIterator set_symmetric_difference (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result)
|
||||
{
|
||||
typedef typename iterator_traits<InputIterator1>::value_type value_type;
|
||||
return (set_symmetric_difference (first1, last1, first2, last2, result, less<value_type>()));
|
||||
}
|
||||
|
||||
/// \brief Returns true if the given range is sorted.
|
||||
/// \ingroup ConditionAlgorithms
|
||||
template <typename ForwardIterator>
|
||||
inline bool is_sorted (ForwardIterator first, ForwardIterator last)
|
||||
{
|
||||
typedef typename iterator_traits<ForwardIterator>::value_type value_type;
|
||||
return (is_sorted (first, last, less<value_type>()));
|
||||
}
|
||||
|
||||
/// \brief Compares two given containers like strcmp compares strings.
|
||||
/// \ingroup ConditionAlgorithms
|
||||
template <typename InputIterator1, typename InputIterator2>
|
||||
inline bool lexicographical_compare (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)
|
||||
{
|
||||
typedef typename iterator_traits<InputIterator1>::value_type value_type;
|
||||
return (lexicographical_compare (first1, last1, first2, last2, less<value_type>()));
|
||||
}
|
||||
|
||||
/// \brief Creates the next lexicographical permutation of [first,last).
|
||||
/// Returns false if no further permutations can be created.
|
||||
/// \ingroup GeneratorAlgorithms
|
||||
template <typename BidirectionalIterator>
|
||||
inline bool next_permutation (BidirectionalIterator first, BidirectionalIterator last)
|
||||
{
|
||||
typedef typename iterator_traits<BidirectionalIterator>::value_type value_type;
|
||||
return (next_permutation (first, last, less<value_type>()));
|
||||
}
|
||||
|
||||
/// \brief Creates the previous lexicographical permutation of [first,last).
|
||||
/// Returns false if no further permutations can be created.
|
||||
/// \ingroup GeneratorAlgorithms
|
||||
template <typename BidirectionalIterator>
|
||||
inline bool prev_permutation (BidirectionalIterator first, BidirectionalIterator last)
|
||||
{
|
||||
typedef typename iterator_traits<BidirectionalIterator>::value_type value_type;
|
||||
return (prev_permutation (first, last, less<value_type>()));
|
||||
}
|
||||
|
||||
/// \brief Returns iterator to the max element in [first,last)
|
||||
/// \ingroup SearchingAlgorithms
|
||||
template <typename ForwardIterator>
|
||||
inline ForwardIterator max_element (ForwardIterator first, ForwardIterator last)
|
||||
{
|
||||
typedef typename iterator_traits<ForwardIterator>::value_type value_type;
|
||||
return (max_element (first, last, less<value_type>()));
|
||||
}
|
||||
|
||||
/// \brief Returns iterator to the min element in [first,last)
|
||||
/// \ingroup SearchingAlgorithms
|
||||
template <typename ForwardIterator>
|
||||
inline ForwardIterator min_element (ForwardIterator first, ForwardIterator last)
|
||||
{
|
||||
typedef typename iterator_traits<ForwardIterator>::value_type value_type;
|
||||
return (min_element (first, last, less<value_type>()));
|
||||
}
|
||||
|
||||
/// \brief Makes [first,middle) a part of the sorted array.
|
||||
/// Contents of [middle,last) is undefined. This implementation just calls stable_sort.
|
||||
/// \ingroup SortingAlgorithms
|
||||
template <typename RandomAccessIterator>
|
||||
inline void partial_sort (RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last)
|
||||
{
|
||||
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
partial_sort (first, middle, last, less<value_type>());
|
||||
}
|
||||
|
||||
/// \brief Puts \p nth element into its sorted position.
|
||||
/// In this implementation, the entire array is sorted. I can't think of any
|
||||
/// use for it where the time gained would be useful.
|
||||
/// \ingroup SortingAlgorithms
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename RandomAccessIterator>
|
||||
inline void nth_element (RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last)
|
||||
{
|
||||
partial_sort (first, nth, last);
|
||||
}
|
||||
|
||||
/// \brief Like partial_sort, but outputs to [result_first,result_last)
|
||||
/// \ingroup SortingAlgorithms
|
||||
template <typename InputIterator, typename RandomAccessIterator>
|
||||
inline RandomAccessIterator partial_sort_copy (InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last)
|
||||
{
|
||||
typedef typename iterator_traits<InputIterator>::value_type value_type;
|
||||
return (partial_sort_copy (first, last, result_first, result_last, less<value_type>()));
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,293 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// ualgobase.cc
|
||||
//
|
||||
// Copy and fill optimizations are here.
|
||||
//
|
||||
|
||||
#ifndef NDEBUG // Optimized code here. asserts slow it down, and are checked elsewhere.
|
||||
#define NDEBUG
|
||||
#endif
|
||||
|
||||
#include "ualgo.h"
|
||||
|
||||
#undef CPU_HAS_MMX
|
||||
|
||||
namespace ustl {
|
||||
|
||||
// Generic version for implementing fill_nX_fast on non-i386 architectures.
|
||||
template <typename T> inline void stosv (T*& p, size_t n, T v)
|
||||
{ while (n--) *p++ = v; }
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Copy functions
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
static inline void movsb_dir_up (void) __attribute__((always_inline));
|
||||
static inline void movsb_dir_down (void) __attribute__((always_inline));
|
||||
static inline void movsb (const void*& src, size_t nBytes, void*& dest) __attribute__((always_inline));
|
||||
static inline void movsd (const void*& src, size_t nWords, void*& dest) __attribute__((always_inline));
|
||||
#endif
|
||||
|
||||
static inline void movsb_dir_up (void) { asm volatile ("cld"); }
|
||||
static inline void movsb_dir_down (void) { asm volatile ("std"); }
|
||||
|
||||
static inline void movsb (const void*& src, size_t nBytes, void*& dest)
|
||||
{
|
||||
asm volatile ("rep;\n\tmovsb"
|
||||
: "=&S"(src), "=&D"(dest), "=&c"(nBytes)
|
||||
: "0"(src), "1"(dest), "2"(nBytes)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void movsd (const void*& src, size_t nWords, void*& dest)
|
||||
{
|
||||
asm volatile ("rep;\n\tmovsl"
|
||||
: "=&S"(src), "=&D"(dest), "=&c"(nWords)
|
||||
: "0"(src), "1"(dest), "2"(nWords)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
template <> inline void stosv (uint8_t*& p, size_t n, uint8_t v)
|
||||
{ asm volatile ("rep;\n\tstosb" : "=&D"(p), "=c"(n) : "0"(p), "1"(n), "a"(v) : "memory"); }
|
||||
template <> inline void stosv (uint16_t*& p, size_t n, uint16_t v)
|
||||
{ asm volatile ("rep;\n\tstosw" : "=&D"(p), "=c"(n) : "0"(p), "1"(n), "a"(v) : "memory"); }
|
||||
template <> inline void stosv (uint32_t*& p, size_t n, uint32_t v)
|
||||
{ asm volatile ("rep;\n\tstosl" : "=&D"(p), "=c"(n) : "0"(p), "1"(n), "a"(v) : "memory"); }
|
||||
|
||||
#if CPU_HAS_MMX
|
||||
#define MMX_ALIGN 16U // Data must be aligned on this grain
|
||||
#define MMX_BS 32U // Assembly routines copy data this many bytes at a time.
|
||||
|
||||
static inline void simd_block_copy (const void* src, void* dest) __attribute__((always_inline));
|
||||
static inline void simd_block_store (uint8_t* dest) __attribute__((always_inline));
|
||||
static inline void simd_block_cleanup (void) __attribute__((always_inline));
|
||||
|
||||
static inline void simd_block_copy (const void* src, void* dest)
|
||||
{
|
||||
const char* csrc ((const char*) src);
|
||||
char* cdest ((char*) dest);
|
||||
#if CPU_HAS_SSE
|
||||
asm (
|
||||
"movaps\t%2, %%xmm0 \n\t"
|
||||
"movaps\t%3, %%xmm1 \n\t"
|
||||
"movntps\t%%xmm0, %0 \n\t"
|
||||
"movntps\t%%xmm1, %1"
|
||||
: "=m"(cdest[0]), "=m"(cdest[16])
|
||||
: "m"(csrc[0]), "m"(csrc[16])
|
||||
: "xmm0", "xmm1");
|
||||
#else
|
||||
asm (
|
||||
"movq %4, %%mm0 \n\t"
|
||||
"movq %5, %%mm1 \n\t"
|
||||
"movq %6, %%mm2 \n\t"
|
||||
"movq %7, %%mm3 \n\t"
|
||||
"movq %%mm0, %0 \n\t"
|
||||
"movq %%mm1, %1 \n\t"
|
||||
"movq %%mm2, %2 \n\t"
|
||||
"movq %%mm3, %3"
|
||||
: "=m"(cdest[0]), "=m"(cdest[8]), "=m"(cdest[16]), "=m"(cdest[24])
|
||||
: "m"(csrc[0]), "m"(csrc[8]), "m"(csrc[16]), "m"(csrc[24])
|
||||
: "mm0", "mm1", "mm2", "mm3", "st", "st(1)", "st(2)", "st(3)");
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void simd_block_store (uint8_t* dest)
|
||||
{
|
||||
#if CPU_HAS_SSE
|
||||
asm volatile (
|
||||
"movntq %%mm0, %0\n\t"
|
||||
"movntq %%mm0, %1\n\t"
|
||||
"movntq %%mm0, %2\n\t"
|
||||
"movntq %%mm0, %3"
|
||||
: "=m"(dest[0]), "=m"(dest[8]), "=m"(dest[16]), "=m"(dest[24]));
|
||||
#else
|
||||
asm volatile (
|
||||
"movq %%mm0, %0 \n\t"
|
||||
"movq %%mm0, %1 \n\t"
|
||||
"movq %%mm0, %2 \n\t"
|
||||
"movq %%mm0, %3"
|
||||
: "=m"(dest[0]), "=m"(dest[8]), "=m"(dest[16]), "=m"(dest[24]));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void simd_block_cleanup (void)
|
||||
{
|
||||
#if !CPU_HAS_SSE
|
||||
simd::reset_mmx();
|
||||
#endif
|
||||
asm volatile ("sfence");
|
||||
}
|
||||
|
||||
/// The fastest optimized raw memory copy.
|
||||
void copy_n_fast (const void* src, size_t nBytes, void* dest)
|
||||
{
|
||||
movsb_dir_up();
|
||||
size_t nHeadBytes = Align(uintptr_t(src), MMX_ALIGN) - uintptr_t(src);
|
||||
nHeadBytes = min (nHeadBytes, nBytes);
|
||||
movsb (src, nHeadBytes, dest);
|
||||
nBytes -= nHeadBytes;
|
||||
if (!(uintptr_t(dest) % MMX_ALIGN)) {
|
||||
const size_t nMiddleBlocks = nBytes / MMX_BS;
|
||||
for (uoff_t i = 0; i < nMiddleBlocks; ++ i) {
|
||||
prefetch (advance (src, 512), 0, 0);
|
||||
simd_block_copy (src, dest);
|
||||
src = advance (src, MMX_BS);
|
||||
dest = advance (dest, MMX_BS);
|
||||
}
|
||||
simd_block_cleanup();
|
||||
nBytes %= MMX_BS;
|
||||
}
|
||||
movsb (src, nBytes, dest);
|
||||
}
|
||||
#endif // CPU_HAS_MMX
|
||||
|
||||
/// The fastest optimized backwards raw memory copy.
|
||||
void copy_backward_fast (const void* first, const void* last, void* result)
|
||||
{
|
||||
prefetch (first, 0, 0);
|
||||
prefetch (result, 1, 0);
|
||||
size_t nBytes (distance (first, last));
|
||||
movsb_dir_down();
|
||||
size_t nHeadBytes = uintptr_t(last) % 4;
|
||||
last = advance (last, -1);
|
||||
result = advance (result, -1);
|
||||
movsb (last, nHeadBytes, result);
|
||||
nBytes -= nHeadBytes;
|
||||
if (uintptr_t(result) % 4 == 3) {
|
||||
const size_t nMiddleBlocks = nBytes / 4;
|
||||
last = advance (last, -3);
|
||||
result = advance (result, -3);
|
||||
movsd (last, nMiddleBlocks, result);
|
||||
nBytes %= 4;
|
||||
}
|
||||
movsb (last, nBytes, result);
|
||||
movsb_dir_up();
|
||||
}
|
||||
#endif // __i386__
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Fill functions
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#if CPU_HAS_MMX
|
||||
template <typename T> inline void build_block (T) {}
|
||||
template <> inline void build_block (uint8_t v)
|
||||
{
|
||||
asm volatile (
|
||||
"movd %0, %%mm0\n\tpunpcklbw %%mm0, %%mm0\n\tpshufw $0, %%mm0, %%mm0"
|
||||
: : "g"(uint32_t(v)) : "mm0");
|
||||
}
|
||||
template <> inline void build_block (uint16_t v)
|
||||
{
|
||||
asm volatile (
|
||||
"movd %0, %%mm0\n\tpshufw $0, %%mm0, %%mm0"
|
||||
: : "g"(uint32_t(v)) : "mm0");
|
||||
}
|
||||
template <> inline void build_block (uint32_t v)
|
||||
{
|
||||
asm volatile (
|
||||
"movd %0, %%mm0\n\tpunpckldq %%mm0, %%mm0"
|
||||
: : "g"(uint32_t(v)) : "mm0");
|
||||
}
|
||||
|
||||
static inline void simd_block_fill_loop (uint8_t*& dest, size_t count)
|
||||
{
|
||||
prefetch (advance (dest, 512), 1, 0);
|
||||
for (uoff_t i = 0; i < count; ++ i, dest += MMX_BS)
|
||||
simd_block_store (dest);
|
||||
simd_block_cleanup();
|
||||
simd::reset_mmx();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void fill_n_fast (T* dest, size_t count, T v)
|
||||
{
|
||||
size_t nHead = Align(uintptr_t(dest), MMX_ALIGN) - uintptr_t(dest) / sizeof(T);
|
||||
nHead = min (nHead, count);
|
||||
stosv (dest, nHead, v);
|
||||
count -= nHead;
|
||||
build_block (v);
|
||||
simd_block_fill_loop ((uint8_t*&) dest, count * sizeof(T) / MMX_BS);
|
||||
count %= MMX_BS;
|
||||
stosv (dest, count, v);
|
||||
}
|
||||
|
||||
void fill_n8_fast (uint8_t* dest, size_t count, uint8_t v)
|
||||
{ fill_n_fast (dest, count, v); }
|
||||
void fill_n16_fast (uint16_t* dest, size_t count, uint16_t v)
|
||||
{ fill_n_fast (dest, count, v); }
|
||||
void fill_n32_fast (uint32_t* dest, size_t count, uint32_t v)
|
||||
{ fill_n_fast (dest, count, v); }
|
||||
#else
|
||||
void fill_n8_fast (uint8_t* dest, size_t count, uint8_t v) { memset (dest, v, count); }
|
||||
void fill_n16_fast (uint16_t* dest, size_t count, uint16_t v) { stosv (dest, count, v); }
|
||||
void fill_n32_fast (uint32_t* dest, size_t count, uint32_t v) { stosv (dest, count, v); }
|
||||
#endif // CPU_HAS_MMX
|
||||
|
||||
/// Exchanges ranges [first, middle) and [middle, last)
|
||||
void rotate_fast (void* first, void* middle, void* last)
|
||||
{
|
||||
#ifdef HAVE_ALLOCA_H
|
||||
const size_t half1 (distance (first, middle)), half2 (distance (middle, last));
|
||||
const size_t hmin (min (half1, half2));
|
||||
if (!hmin) {
|
||||
return;
|
||||
}
|
||||
void* buf = alloca (hmin);
|
||||
if (buf) {
|
||||
if (half2 < half1) {
|
||||
copy_n_fast (middle, half2, buf);
|
||||
copy_backward_fast (first, middle, last);
|
||||
copy_n_fast (buf, half2, first);
|
||||
} else {
|
||||
copy_n_fast (first, half1, buf);
|
||||
copy_n_fast (middle, half2, first);
|
||||
copy_n_fast (buf, half1, advance (first, half2));
|
||||
}
|
||||
} else
|
||||
#else
|
||||
if (first == middle || middle == last) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
char* f = (char*) first;
|
||||
char* m = (char*) middle;
|
||||
char* l = (char*) last;
|
||||
reverse (f, m);
|
||||
reverse (m, l);
|
||||
while (f != m && m != l)
|
||||
iter_swap (f++, --l);
|
||||
reverse (f, (f == m ? l : m));
|
||||
}
|
||||
}
|
||||
|
||||
#if __GNUC__ < 4
|
||||
size_t popcount (uint32_t v)
|
||||
{
|
||||
const uint32_t w = v - ((v >> 1) & 0x55555555); // Algorithm from AMD optimization guide
|
||||
const uint32_t x = (w & 0x33333333) + ((w >> 2) & 0x33333333);
|
||||
return (((x + (x >> 4) & 0x0F0F0F0F) * 0x01010101) >> 24);
|
||||
}
|
||||
|
||||
#if HAVE_INT64_T
|
||||
/// \brief Returns the number of 1s in \p v in binary.
|
||||
size_t popcount (uint64_t v)
|
||||
{
|
||||
v -= (v >> 1) & UINT64_C(0x5555555555555555); // Algorithm from Wikipedia
|
||||
v = (v & UINT64_C(0x3333333333333333)) + ((v >> 2) & UINT64_C(0x3333333333333333));
|
||||
v = (v + (v >> 4)) & UINT64_C(0x0F0F0F0F0F0F0F0F);
|
||||
return ((v * UINT64_C(0x0101010101010101)) >> 56);
|
||||
}
|
||||
#endif // HAVE_INT64_T
|
||||
#endif // !__GNUC__
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
@@ -1,334 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// ualgobase.h
|
||||
//
|
||||
// Implementation of STL algorithms.
|
||||
//
|
||||
// The function prototypes are copied
|
||||
// exactly from the SGI version of STL documentation along with comments about
|
||||
// their use. The code is NOT the same, though the functionality usually is.
|
||||
//
|
||||
|
||||
#ifndef UALGOBASE_H_683A0BE77546133C4CE0E3622CFAA2EB
|
||||
#define UALGOBASE_H_683A0BE77546133C4CE0E3622CFAA2EB
|
||||
|
||||
#include "uutility.h"
|
||||
#include <string.h>
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
#include <stdio.h>
|
||||
#undef CPU_HAS_MMX
|
||||
#endif
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// Assigns the contents of a to b and the contents of b to a.
|
||||
/// This is used as a primitive operation by many other algorithms.
|
||||
/// \ingroup SwapAlgorithms
|
||||
///
|
||||
template <typename Assignable>
|
||||
inline void swap (Assignable& a, Assignable& b)
|
||||
{
|
||||
Assignable tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
}
|
||||
|
||||
/// Equivalent to swap (*a, *b)
|
||||
/// \ingroup SwapAlgorithms
|
||||
///
|
||||
template <typename Iterator>
|
||||
inline void iter_swap (Iterator a, Iterator b)
|
||||
{
|
||||
swap (*a, *b);
|
||||
}
|
||||
|
||||
/// Copy copies elements from the range [first, last) to the range
|
||||
/// [result, result + (last - first)). That is, it performs the assignments
|
||||
/// *result = *first, *(result + 1) = *(first + 1), and so on. [1] Generally,
|
||||
/// for every integer n from 0 to last - first, copy performs the assignment
|
||||
/// *(result + n) = *(first + n). Assignments are performed in forward order,
|
||||
/// i.e. in order of increasing n.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
|
||||
{
|
||||
for (; first != last; ++result, ++first)
|
||||
*result = *first;
|
||||
return (result);
|
||||
}
|
||||
|
||||
/// Copy_n copies elements from the range [first, first + n) to the range
|
||||
/// [result, result + n). That is, it performs the assignments
|
||||
/// *result = *first, *(result + 1) = *(first + 1), and so on. Generally,
|
||||
/// for every integer i from 0 up to (but not including) n, copy_n performs
|
||||
/// the assignment *(result + i) = *(first + i). Assignments are performed
|
||||
/// in forward order, i.e. in order of increasing n.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator copy_n (InputIterator first, size_t count, OutputIterator result)
|
||||
{
|
||||
for (; count; --count, ++result, ++first)
|
||||
*result = *first;
|
||||
return (result);
|
||||
}
|
||||
|
||||
/// \brief Copy copies elements from the range (last, first] to result.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
/// Copies elements starting at last, decrementing both last and result.
|
||||
///
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator copy_backward (InputIterator first, InputIterator last, OutputIterator result)
|
||||
{
|
||||
while (first != last)
|
||||
*--result = *--last;
|
||||
return (result);
|
||||
}
|
||||
|
||||
/// For_each applies the function object f to each element in the range
|
||||
/// [first, last); f's return value, if any, is ignored. Applications are
|
||||
/// performed in forward order, i.e. from first to last. For_each returns
|
||||
/// the function object after it has been applied to each element.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename InputIterator, typename UnaryFunction>
|
||||
inline UnaryFunction for_each (InputIterator first, InputIterator last, UnaryFunction f)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
f (*first);
|
||||
return (f);
|
||||
}
|
||||
|
||||
/// Fill assigns the value value to every element in the range [first, last).
|
||||
/// That is, for every iterator i in [first, last),
|
||||
/// it performs the assignment *i = value.
|
||||
/// \ingroup GeneratorAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator, typename T>
|
||||
inline void fill (ForwardIterator first, ForwardIterator last, const T& value)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
*first = value;
|
||||
}
|
||||
|
||||
/// Fill_n assigns the value value to every element in the range
|
||||
/// [first, first+count). That is, for every iterator i in [first, first+count),
|
||||
/// it performs the assignment *i = value. The return value is first + count.
|
||||
/// \ingroup GeneratorAlgorithms
|
||||
///
|
||||
template <typename OutputIterator, typename T>
|
||||
inline OutputIterator fill_n (OutputIterator first, size_t count, const T& value)
|
||||
{
|
||||
for (; count; --count, ++first)
|
||||
*first = value;
|
||||
return (first);
|
||||
}
|
||||
|
||||
#if CPU_HAS_MMX
|
||||
extern "C" void copy_n_fast (const void* src, size_t count, void* dest);
|
||||
#else
|
||||
inline void copy_n_fast (const void* src, size_t count, void* dest)
|
||||
{ memcpy (dest, src, count); }
|
||||
#endif
|
||||
#if __i386__ || __x86_64__
|
||||
extern "C" void copy_backward_fast (const void* first, const void* last, void* result);
|
||||
#else
|
||||
inline void copy_backward_fast (const void* first, const void* last, void* result)
|
||||
{
|
||||
const size_t nBytes (distance (first, last));
|
||||
memmove (advance (result, -nBytes), first, nBytes);
|
||||
}
|
||||
#endif
|
||||
extern "C" void fill_n8_fast (uint8_t* dest, size_t count, uint8_t v);
|
||||
extern "C" void fill_n16_fast (uint16_t* dest, size_t count, uint16_t v);
|
||||
extern "C" void fill_n32_fast (uint32_t* dest, size_t count, uint32_t v);
|
||||
extern "C" void rotate_fast (void* first, void* middle, void* last);
|
||||
|
||||
#if __GNUC__ >= 4
|
||||
/// \brief Computes the number of 1 bits in a number.
|
||||
/// \ingroup ConditionAlgorithms
|
||||
inline size_t popcount (uint32_t v) { return (__builtin_popcount (v)); }
|
||||
#if HAVE_INT64_T
|
||||
inline size_t popcount (uint64_t v) { return (__builtin_popcountll (v)); }
|
||||
#endif
|
||||
#else
|
||||
size_t popcount (uint32_t v);
|
||||
#if HAVE_INT64_T
|
||||
size_t popcount (uint64_t v);
|
||||
#endif // HAVE_INT64_T
|
||||
#endif // __GNUC__
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Optimized versions for standard types
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#if WANT_UNROLLED_COPY
|
||||
|
||||
template <typename T>
|
||||
inline T* unrolled_copy (const T* first, size_t count, T* result)
|
||||
{
|
||||
copy_n_fast (first, count * sizeof(T), result);
|
||||
return (advance (result, count));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint8_t* copy_backward (const uint8_t* first, const uint8_t* last, uint8_t* result)
|
||||
{
|
||||
copy_backward_fast (first, last, result);
|
||||
return (result);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T* unrolled_fill (T* result, size_t count, T value)
|
||||
{
|
||||
for (; count; --count, ++result)
|
||||
*result = value;
|
||||
return (result);
|
||||
}
|
||||
template <> inline uint8_t* unrolled_fill (uint8_t* result, size_t count, uint8_t value)
|
||||
{ fill_n8_fast (result, count, value); return (advance (result, count)); }
|
||||
template <> inline uint16_t* unrolled_fill (uint16_t* result, size_t count, uint16_t value)
|
||||
{ fill_n16_fast (result, count, value); return (advance (result, count)); }
|
||||
template <> inline uint32_t* unrolled_fill (uint32_t* result, size_t count, uint32_t value)
|
||||
{ fill_n32_fast (result, count, value); return (advance (result, count)); }
|
||||
template <> inline float* unrolled_fill (float* result, size_t count, float value)
|
||||
{ fill_n32_fast ((uint32_t*) result, count, noalias(uint32_t(),&value)); return (advance (result, count)); }
|
||||
|
||||
#if CPU_HAS_MMX
|
||||
#define UNROLLED_COPY_SPECIALIZATION(type) \
|
||||
template <> inline type* copy (const type* first, const type* last, type* result) \
|
||||
{ return (unrolled_copy (first, distance (first, last), result)); } \
|
||||
template <> inline type* copy_n (const type* first, size_t count, type* result) \
|
||||
{ return (unrolled_copy (first, count, result)); }
|
||||
#define UNROLLED_FILL_SPECIALIZATION(type) \
|
||||
template <> inline void fill (type* first, type* last, const type& value) \
|
||||
{ unrolled_fill (first, distance (first, last), value); } \
|
||||
template <> inline type* fill_n (type* first, size_t count, const type& value) \
|
||||
{ return (unrolled_fill (first, count, value)); }
|
||||
UNROLLED_COPY_SPECIALIZATION(uint8_t)
|
||||
UNROLLED_FILL_SPECIALIZATION(uint8_t)
|
||||
UNROLLED_COPY_SPECIALIZATION(uint16_t)
|
||||
UNROLLED_FILL_SPECIALIZATION(uint16_t)
|
||||
UNROLLED_COPY_SPECIALIZATION(uint32_t)
|
||||
UNROLLED_FILL_SPECIALIZATION(uint32_t)
|
||||
UNROLLED_COPY_SPECIALIZATION(float)
|
||||
UNROLLED_FILL_SPECIALIZATION(float)
|
||||
#undef UNROLLED_FILL_SPECIALIZATION
|
||||
#undef UNROLLED_COPY_SPECIALIZATION
|
||||
#endif // WANT_UNROLLED_COPY
|
||||
#endif // CPU_HAS_MMX
|
||||
|
||||
// Specializations for void* and char*, aliasing the above optimized versions.
|
||||
//
|
||||
// All these need duplication with const and non-const arguments, since
|
||||
// otherwise the compiler will default to the unoptimized version for
|
||||
// pointers not const in the caller's context, such as local variables.
|
||||
// These are all inline, but they sure slow down compilation... :(
|
||||
//
|
||||
#define COPY_ALIAS_FUNC(ctype, type, alias_type) \
|
||||
template <> inline type* copy (ctype* first, ctype* last, type* result) \
|
||||
{ return ((type*) copy ((const alias_type*) first, (const alias_type*) last, (alias_type*) result)); }
|
||||
#if WANT_UNROLLED_COPY
|
||||
#if HAVE_THREE_CHAR_TYPES
|
||||
COPY_ALIAS_FUNC(const char, char, uint8_t)
|
||||
COPY_ALIAS_FUNC(char, char, uint8_t)
|
||||
#endif
|
||||
COPY_ALIAS_FUNC(const int8_t, int8_t, uint8_t)
|
||||
COPY_ALIAS_FUNC(int8_t, int8_t, uint8_t)
|
||||
COPY_ALIAS_FUNC(uint8_t, uint8_t, uint8_t)
|
||||
COPY_ALIAS_FUNC(const int16_t, int16_t, uint16_t)
|
||||
COPY_ALIAS_FUNC(int16_t, int16_t, uint16_t)
|
||||
COPY_ALIAS_FUNC(uint16_t, uint16_t, uint16_t)
|
||||
#if CPU_HAS_MMX || (SIZE_OF_LONG > 4)
|
||||
COPY_ALIAS_FUNC(const int32_t, int32_t, uint32_t)
|
||||
COPY_ALIAS_FUNC(int32_t, int32_t, uint32_t)
|
||||
COPY_ALIAS_FUNC(uint32_t, uint32_t, uint32_t)
|
||||
#endif
|
||||
#endif
|
||||
COPY_ALIAS_FUNC(const void, void, uint8_t)
|
||||
COPY_ALIAS_FUNC(void, void, uint8_t)
|
||||
#undef COPY_ALIAS_FUNC
|
||||
#define COPY_BACKWARD_ALIAS_FUNC(ctype, type, alias_type) \
|
||||
template <> inline type* copy_backward (ctype* first, ctype* last, type* result) \
|
||||
{ return ((type*) copy_backward ((const alias_type*) first, (const alias_type*) last, (alias_type*) result)); }
|
||||
#if WANT_UNROLLED_COPY
|
||||
#if HAVE_THREE_CHAR_TYPES
|
||||
COPY_BACKWARD_ALIAS_FUNC(char, char, uint8_t)
|
||||
#endif
|
||||
COPY_BACKWARD_ALIAS_FUNC(uint8_t, uint8_t, uint8_t)
|
||||
COPY_BACKWARD_ALIAS_FUNC(int8_t, int8_t, uint8_t)
|
||||
COPY_BACKWARD_ALIAS_FUNC(uint16_t, uint16_t, uint8_t)
|
||||
COPY_BACKWARD_ALIAS_FUNC(const uint16_t, uint16_t, uint8_t)
|
||||
COPY_BACKWARD_ALIAS_FUNC(int16_t, int16_t, uint8_t)
|
||||
COPY_BACKWARD_ALIAS_FUNC(const int16_t, int16_t, uint8_t)
|
||||
#endif
|
||||
COPY_BACKWARD_ALIAS_FUNC(void, void, uint8_t)
|
||||
COPY_BACKWARD_ALIAS_FUNC(const void, void, uint8_t)
|
||||
#undef COPY_BACKWARD_ALIAS_FUNC
|
||||
#define FILL_ALIAS_FUNC(type, alias_type, v_type) \
|
||||
template <> inline void fill (type* first, type* last, const v_type& value) \
|
||||
{ fill ((alias_type*) first, (alias_type*) last, (const alias_type&) value); }
|
||||
FILL_ALIAS_FUNC(void, uint8_t, char)
|
||||
FILL_ALIAS_FUNC(void, uint8_t, uint8_t)
|
||||
#if WANT_UNROLLED_COPY
|
||||
#if HAVE_THREE_CHAR_TYPES
|
||||
FILL_ALIAS_FUNC(char, uint8_t, char)
|
||||
FILL_ALIAS_FUNC(char, uint8_t, uint8_t)
|
||||
#endif
|
||||
FILL_ALIAS_FUNC(int8_t, uint8_t, int8_t)
|
||||
FILL_ALIAS_FUNC(int16_t, uint16_t, int16_t)
|
||||
#if CPU_HAS_MMX || (SIZE_OF_LONG > 4)
|
||||
FILL_ALIAS_FUNC(int32_t, uint32_t, int32_t)
|
||||
#endif
|
||||
#endif
|
||||
#undef FILL_ALIAS_FUNC
|
||||
#define COPY_N_ALIAS_FUNC(ctype, type, alias_type) \
|
||||
template <> inline type* copy_n (ctype* first, size_t count, type* result) \
|
||||
{ return ((type*) copy_n ((const alias_type*) first, count, (alias_type*) result)); }
|
||||
COPY_N_ALIAS_FUNC(const void, void, uint8_t)
|
||||
COPY_N_ALIAS_FUNC(void, void, uint8_t)
|
||||
#if WANT_UNROLLED_COPY
|
||||
#if HAVE_THREE_CHAR_TYPES
|
||||
COPY_N_ALIAS_FUNC(const char, char, uint8_t)
|
||||
COPY_N_ALIAS_FUNC(char, char, uint8_t)
|
||||
#endif
|
||||
COPY_N_ALIAS_FUNC(int8_t, int8_t, uint8_t)
|
||||
COPY_N_ALIAS_FUNC(uint8_t, uint8_t, uint8_t)
|
||||
COPY_N_ALIAS_FUNC(const int8_t, int8_t, uint8_t)
|
||||
COPY_N_ALIAS_FUNC(int16_t, int16_t, uint16_t)
|
||||
COPY_N_ALIAS_FUNC(uint16_t, uint16_t, uint16_t)
|
||||
COPY_N_ALIAS_FUNC(const int16_t, int16_t, uint16_t)
|
||||
#if CPU_HAS_MMX || (SIZE_OF_LONG > 4)
|
||||
COPY_N_ALIAS_FUNC(int32_t, int32_t, uint32_t)
|
||||
COPY_N_ALIAS_FUNC(uint32_t, uint32_t, uint32_t)
|
||||
COPY_N_ALIAS_FUNC(const int32_t, int32_t, uint32_t)
|
||||
#endif
|
||||
#endif
|
||||
#undef COPY_N_ALIAS_FUNC
|
||||
#define FILL_N_ALIAS_FUNC(type, alias_type, v_type) \
|
||||
template <> inline type* fill_n (type* first, size_t n, const v_type& value) \
|
||||
{ return ((type*) fill_n ((alias_type*) first, n, (const alias_type&) value)); }
|
||||
FILL_N_ALIAS_FUNC(void, uint8_t, char)
|
||||
FILL_N_ALIAS_FUNC(void, uint8_t, uint8_t)
|
||||
#if WANT_UNROLLED_COPY
|
||||
#if HAVE_THREE_CHAR_TYPES
|
||||
FILL_N_ALIAS_FUNC(char, uint8_t, char)
|
||||
FILL_N_ALIAS_FUNC(char, uint8_t, uint8_t)
|
||||
#endif
|
||||
FILL_N_ALIAS_FUNC(int8_t, uint8_t, int8_t)
|
||||
FILL_N_ALIAS_FUNC(int16_t, uint16_t, int16_t)
|
||||
#if CPU_HAS_MMX || (SIZE_OF_LONG > 4)
|
||||
FILL_N_ALIAS_FUNC(int32_t, uint32_t, int32_t)
|
||||
#endif
|
||||
#endif
|
||||
#undef FILL_N_ALIAS_FUNC
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// uassert.h
|
||||
|
||||
#ifndef UASSERT_H
|
||||
#define UASSERT_H
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
#include <stdio.h>
|
||||
|
||||
#undef assert
|
||||
#define assert(x) _uassert((x), #x, __FILE__, __LINE__)
|
||||
|
||||
static void _uassert(int x, const char *xstr, const char *file, int line) {
|
||||
if (!x) {
|
||||
printf("assert %s failed at %s:%d\n", xstr, file, line);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,38 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// ubitset.cc
|
||||
//
|
||||
|
||||
#include "ubitset.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// Copies bits from \p v of size \p n into \p buf as MSB "1011001..." LSB
|
||||
/// If \p buf is too small, MSB bits will be truncated.
|
||||
void convert_to_bitstring (const bitset_value_type* v, size_t n, string& buf)
|
||||
{
|
||||
string::iterator stri = buf.end();
|
||||
for (size_t i = 0; i < n && stri > buf.begin(); ++ i)
|
||||
for (bitset_value_type b = 1; b && stri > buf.begin(); b <<= 1)
|
||||
*--stri = (v[i] & b) ? '1' : '0';
|
||||
}
|
||||
|
||||
/// Copies bits from \p buf as MSB "1011001..." LSB into \p v of size \p n.
|
||||
void convert_from_bitstring (const string& buf, bitset_value_type* v, size_t n)
|
||||
{
|
||||
string::const_iterator stri = buf.end();
|
||||
for (size_t i = 0; i < n; ++ i) {
|
||||
for (bitset_value_type b = 1; b; b <<= 1) {
|
||||
if (stri == buf.begin() || *--stri == '0')
|
||||
v[i] &= ~b;
|
||||
else
|
||||
v[i] |= b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// ubitset.h
|
||||
//
|
||||
#ifndef UBITSET_H_7B6450EC1400CBA45DCE0127739F82EE
|
||||
#define UBITSET_H_7B6450EC1400CBA45DCE0127739F82EE
|
||||
|
||||
#include "uassert.h"
|
||||
#include "ustring.h"
|
||||
#include "ufunction.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
typedef uint32_t bitset_value_type;
|
||||
|
||||
void convert_to_bitstring (const bitset_value_type* v, size_t n, string& buf);
|
||||
void convert_from_bitstring (const string& buf, bitset_value_type* v, size_t n);
|
||||
|
||||
/// \class bitset ubitset.h ustl.h
|
||||
/// \ingroup Sequences
|
||||
///
|
||||
/// \brief bitset is a fixed-size block of memory with addressable bits.
|
||||
///
|
||||
/// Normally used for state flags; allows setting and unsetting of individual
|
||||
/// bits as well as bitwise operations on the entire set. The interface is
|
||||
/// most like that of unsigned integers, and is intended to be used as such.
|
||||
/// If you were using begin() and end() functions in STL's bitset, you would
|
||||
/// not be able to do the same thing here, because those functions return
|
||||
/// host type iterators, not bits.
|
||||
///
|
||||
template <size_t Size>
|
||||
class bitset {
|
||||
public:
|
||||
typedef bitset_value_type value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef const value_type* const_pointer;
|
||||
typedef pointer iterator;
|
||||
typedef const_pointer const_iterator;
|
||||
typedef size_t difference_type;
|
||||
typedef size_t size_type;
|
||||
private:
|
||||
static const size_t s_WordBits = BitsInType (value_type);
|
||||
static const size_t s_nWords = Size / s_WordBits + ((Size % s_WordBits) != 0);
|
||||
static const size_t s_nBits = s_nWords * s_WordBits;
|
||||
private:
|
||||
inline value_type& BitRef (uoff_t n) { assert (n < Size); return (m_Bits [n / s_WordBits]); }
|
||||
inline const value_type BitRef (uoff_t n) const { assert (n < Size); return (m_Bits [n / s_WordBits]); }
|
||||
inline const value_type Mask (uoff_t n) const { assert (n < Size); return (1 << (n % s_WordBits)); }
|
||||
public:
|
||||
inline bitset (value_type v = 0) { fill_n (m_Bits, s_nWords, 0); m_Bits[0] = v; }
|
||||
inline bitset (const string& buf) { convert_from_bitstring (buf, m_Bits, s_nWords); }
|
||||
inline void flip (uoff_t n) { BitRef(n) ^= Mask(n); }
|
||||
inline void reset (void) { fill_n (m_Bits, s_nWords, 0); }
|
||||
inline void clear (void) { fill_n (m_Bits, s_nWords, 0); }
|
||||
inline void set (void) { fill_n (m_Bits, s_nWords, -1); }
|
||||
inline bitset operator~ (void) const { bitset rv (*this); rv.flip(); return (rv); }
|
||||
inline size_type size (void) const { return (Size); }
|
||||
inline size_type capacity (void) const { return (s_nBits); }
|
||||
inline const bool test (uoff_t n) const { return (BitRef(n) & Mask(n)); }
|
||||
inline const bool operator[] (uoff_t n) const { return (test(n)); }
|
||||
inline const_iterator begin (void) const { return (m_Bits); }
|
||||
inline iterator begin (void) { return (m_Bits); }
|
||||
inline const_iterator end (void) const { return (m_Bits + s_nWords); }
|
||||
inline iterator end (void) { return (m_Bits + s_nWords); }
|
||||
/// Returns the value_type with the equivalent bits. If size() > 1, you'll get only the first BitsInType(value_type) bits.
|
||||
inline const value_type to_value (void) const { return (m_Bits[0]); }
|
||||
/// Flips all the bits in the set.
|
||||
inline void flip (void) { transform (begin(), end(), begin(), bitwise_not<value_type>()); }
|
||||
/// Sets or clears bit \p n.
|
||||
inline void set (uoff_t n, bool val = true)
|
||||
{
|
||||
value_type& br (BitRef (n));
|
||||
const value_type mask (Mask (n));
|
||||
const value_type bOn (br | mask), bOff (br & ~mask);
|
||||
br = val ? bOn : bOff;
|
||||
}
|
||||
// Sets the value of the bitrange \p first through \p last to the equivalent number of bits from \p v.
|
||||
inline void set (uoff_t first, uoff_t DebugArg(last), value_type v)
|
||||
{
|
||||
#if !PLATFORM_ANDROID
|
||||
assert (size_t (distance (first, last)) <= s_WordBits && "Bit ranges must be 32 bits or smaller");
|
||||
assert (first / s_WordBits == last / s_WordBits && "Bit ranges can not cross dword (4 byte) boundary");
|
||||
assert ((v & BitMask(value_type,distance(first,last))) == v && "The value is too large to fit in the given bit range");
|
||||
#endif
|
||||
BitRef(first) |= v << (first % s_WordBits);
|
||||
}
|
||||
/// Clears the bit \p n.
|
||||
inline void reset (uoff_t n) { set (n, false); }
|
||||
/// Returns a string with bits MSB "001101001..." LSB.
|
||||
inline string to_string (void) const
|
||||
{
|
||||
string rv (Size, '0');
|
||||
convert_to_bitstring (m_Bits, s_nWords, rv);
|
||||
return (rv);
|
||||
}
|
||||
inline value_type at (uoff_t n) const { return (test(n)); }
|
||||
/// Returns the value in bits \p first through \p last.
|
||||
inline value_type at (uoff_t first, uoff_t last) const
|
||||
{
|
||||
assert (size_t (distance (first, last)) <= s_WordBits && "Bit ranges must be 32 bits or smaller");
|
||||
assert (first / s_WordBits == last / s_WordBits && "Bit ranges can not cross dword (4 byte) boundary");
|
||||
return ((BitRef(first) >> (first % s_WordBits)) & BitMask(value_type,distance(first, last)));
|
||||
}
|
||||
inline bool any (void) const { value_type sum = 0; foreach (const_iterator, i, *this) sum |= *i; return (sum); }
|
||||
inline bool none (void) const { return (!any()); }
|
||||
inline size_t count (void) const { size_t sum = 0; foreach (const_iterator, i, *this) sum += popcount(*i); return (sum); }
|
||||
inline bool operator== (const bitset<Size>& v) const
|
||||
{ return (s_nWords == 1 ? (m_Bits[0] == v.m_Bits[0]) : equal (begin(), end(), v.begin())); }
|
||||
inline const bitset operator& (const bitset<Size>& v)
|
||||
{ bitset<Size> result; transform (begin(), end(), v.begin(), result.begin(), bitwise_and<value_type>()); return (result); }
|
||||
inline const bitset operator| (const bitset<Size>& v)
|
||||
{ bitset<Size> result; transform (begin(), end(), v.begin(), result.begin(), bitwise_or<value_type>()); return (result); }
|
||||
inline const bitset operator^ (const bitset<Size>& v)
|
||||
{ bitset<Size> result; transform (begin(), end(), v.begin(), result.begin(), bitwise_xor<value_type>()); return (result); }
|
||||
inline const bitset& operator&= (const bitset<Size>& v)
|
||||
{ transform (begin(), end(), v.begin(), begin(), bitwise_and<value_type>()); return (*this); }
|
||||
inline const bitset& operator|= (const bitset<Size>& v)
|
||||
{ transform (begin(), end(), v.begin(), begin(), bitwise_or<value_type>()); return (*this); }
|
||||
inline const bitset& operator^= (const bitset<Size>& v)
|
||||
{ transform (begin(), end(), v.begin(), begin(), bitwise_xor<value_type>()); return (*this); }
|
||||
private:
|
||||
value_type m_Bits [s_nWords];
|
||||
};
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,482 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// \file uctralgo.h
|
||||
//
|
||||
// \brief Implementation of STL algorithms with container shortcuts.
|
||||
//
|
||||
// The function prototypes are copied
|
||||
// exactly from the SGI version of STL documentation along with comments about
|
||||
// their use. The code is NOT the same, though the functionality usually is.
|
||||
//
|
||||
|
||||
#ifndef UCTRALGO_H_0D1AEDFA74B09791489FE25B1EC644B0
|
||||
#define UCTRALGO_H_0D1AEDFA74B09791489FE25B1EC644B0
|
||||
|
||||
#include "uassert.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// Copy copies elements from the range [first, last) to the range
|
||||
/// [result, result + (last - first)). That is, it performs the assignments
|
||||
/// *result = *first, *(result + 1) = *(first + 1), and so on. [1] Generally,
|
||||
/// for every integer n from 0 to last - first, copy performs the assignment
|
||||
/// *(result + n) = *(first + n). Assignments are performed in forward order,
|
||||
/// i.e. in order of increasing n.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename OutputIterator>
|
||||
inline OutputIterator copy (const Container& ctr, OutputIterator result)
|
||||
{
|
||||
return (copy (ctr.begin(), ctr.end(), result));
|
||||
}
|
||||
|
||||
/// Copy_if copies elements from the range [first, last) to the range
|
||||
/// [result, result + (last - first)) if pred(*i) returns true.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename OutputIterator, typename Predicate>
|
||||
inline OutputIterator copy_if (Container& ctr, OutputIterator result, Predicate pred)
|
||||
{
|
||||
return (copy_if (ctr.begin(), ctr.end(), result, pred));
|
||||
}
|
||||
|
||||
/// For_each applies the function object f to each element in the range
|
||||
/// [first, last); f's return value, if any, is ignored. Applications are
|
||||
/// performed in forward order, i.e. from first to last. For_each returns
|
||||
/// the function object after it has been applied to each element.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename UnaryFunction>
|
||||
inline UnaryFunction for_each (Container& ctr, UnaryFunction f)
|
||||
{
|
||||
return (for_each (ctr.begin(), ctr.end(), f));
|
||||
}
|
||||
|
||||
/// For_each applies the function object f to each element in the range
|
||||
/// [first, last); f's return value, if any, is ignored. Applications are
|
||||
/// performed in forward order, i.e. from first to last. For_each returns
|
||||
/// the function object after it has been applied to each element.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename UnaryFunction>
|
||||
inline UnaryFunction for_each (const Container& ctr, UnaryFunction f)
|
||||
{
|
||||
return (for_each (ctr.begin(), ctr.end(), f));
|
||||
}
|
||||
|
||||
/// Returns the first iterator i in the range [first, last) such that
|
||||
/// *i == value. Returns last if no such iterator exists.
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename Container, typename EqualityComparable>
|
||||
inline typename Container::const_iterator find (const Container& ctr, const EqualityComparable& value)
|
||||
{
|
||||
return (find (ctr.begin(), ctr.end(), value));
|
||||
}
|
||||
template <typename Container, typename EqualityComparable>
|
||||
inline typename Container::iterator find (Container& ctr, const EqualityComparable& value)
|
||||
{
|
||||
return (find (ctr.begin(), ctr.end(), value));
|
||||
}
|
||||
|
||||
/// Returns the first iterator i in the range [first, last) such that
|
||||
/// pred(*i) is true. Returns last if no such iterator exists.
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename Container, typename Predicate>
|
||||
inline typename Container::const_iterator find_if (const Container& ctr, Predicate pred)
|
||||
{
|
||||
return (find_if (ctr.begin(), ctr.end(), pred));
|
||||
}
|
||||
template <typename Container, typename Predicate>
|
||||
inline typename Container::iterator find_if (Container& ctr, Predicate pred)
|
||||
{
|
||||
return (find_if (ctr.begin(), ctr.end(), pred));
|
||||
}
|
||||
|
||||
/// Count finds the number of elements in [first, last) that are equal
|
||||
/// to value. More precisely, the first version of count returns the
|
||||
/// number of iterators i in [first, last) such that *i == value.
|
||||
/// \ingroup ConditionAlgorithms
|
||||
///
|
||||
template <typename Container, typename EqualityComparable>
|
||||
inline size_t count (const Container& ctr, const EqualityComparable& value)
|
||||
{
|
||||
return (count (ctr.begin(), ctr.end(), value));
|
||||
}
|
||||
|
||||
/// Count_if finds the number of elements in [first, last) that satisfy the
|
||||
/// predicate pred. More precisely, the first version of count_if returns the
|
||||
/// number of iterators i in [first, last) such that pred(*i) is true.
|
||||
/// \ingroup ConditionAlgorithms
|
||||
///
|
||||
template <typename Container, typename Predicate>
|
||||
inline size_t count_if (const Container& ctr, Predicate pred)
|
||||
{
|
||||
return (count_if (ctr.begin(), ctr.end(), pred));
|
||||
}
|
||||
|
||||
/// The first version of transform performs the operation op(*i) for each
|
||||
/// iterator i in the range [first, last), and assigns the result of that
|
||||
/// operation to *o, where o is the corresponding output iterator. That is,
|
||||
/// for each n such that 0 <= n < last - first, it performs the assignment
|
||||
/// *(result + n) = op(*(first + n)).
|
||||
/// The return value is result + (last - first).
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename UnaryFunction>
|
||||
inline void transform (Container& ctr, UnaryFunction op)
|
||||
{
|
||||
transform (ctr.begin(), ctr.end(), ctr.begin(), op);
|
||||
}
|
||||
|
||||
/// The first version of transform performs the operation op(*i) for each
|
||||
/// iterator i in the range [first, last), and assigns the result of that
|
||||
/// operation to *o, where o is the corresponding output iterator. That is,
|
||||
/// for each n such that 0 <= n < last - first, it performs the assignment
|
||||
/// *(result + n) = op(*(first + n)).
|
||||
/// The return value is result + (last - first).
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename OutputIterator, typename UnaryFunction>
|
||||
inline OutputIterator transform (Container& ctr, OutputIterator result, UnaryFunction op)
|
||||
{
|
||||
return (transform (ctr.begin(), ctr.end(), result, op));
|
||||
}
|
||||
|
||||
/// The second version of transform is very similar, except that it uses a
|
||||
/// Binary Function instead of a Unary Function: it performs the operation
|
||||
/// op(*i1, *i2) for each iterator i1 in the range [first1, last1) and assigns
|
||||
/// the result to *o, where i2 is the corresponding iterator in the second
|
||||
/// input range and where o is the corresponding output iterator. That is,
|
||||
/// for each n such that 0 <= n < last1 - first1, it performs the assignment
|
||||
/// *(result + n) = op(*(first1 + n), *(first2 + n).
|
||||
/// The return value is result + (last1 - first1).
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename InputIterator, typename OutputIterator, typename BinaryFunction>
|
||||
inline OutputIterator transform (Container& ctr, InputIterator first, OutputIterator result, BinaryFunction op)
|
||||
{
|
||||
return (transform (ctr.begin(), ctr.end(), first, result, op));
|
||||
}
|
||||
|
||||
/// Replace replaces every element in the range [first, last) equal to
|
||||
/// old_value with new_value. That is: for every iterator i,
|
||||
/// if *i == old_value then it performs the assignment *i = new_value.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename T>
|
||||
inline void replace (Container& ctr, const T& old_value, const T& new_value)
|
||||
{
|
||||
replace (ctr.begin(), ctr.end(), old_value, new_value);
|
||||
}
|
||||
|
||||
/// Replace_if replaces every element in the range [first, last) for which
|
||||
/// pred returns true with new_value. That is: for every iterator i, if
|
||||
/// pred(*i) is true then it performs the assignment *i = new_value.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename Predicate, typename T>
|
||||
inline void replace_if (Container& ctr, Predicate pred, const T& new_value)
|
||||
{
|
||||
replace_if (ctr.begin(), ctr.end(), pred, new_value);
|
||||
}
|
||||
|
||||
/// Replace_copy copies elements from the range [first, last) to the range
|
||||
/// [result, result + (last-first)), except that any element equal to old_value
|
||||
/// is not copied; new_value is copied instead. More precisely, for every
|
||||
/// integer n such that 0 <= n < last-first, replace_copy performs the
|
||||
/// assignment *(result+n) = new_value if *(first+n) == old_value, and
|
||||
/// *(result+n) = *(first+n) otherwise.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename OutputIterator, typename T>
|
||||
inline OutputIterator replace_copy (const Container& ctr, OutputIterator result, const T& old_value, const T& new_value)
|
||||
{
|
||||
return (replace_copy (ctr.begin(), ctr.end(), result, old_value, new_value));
|
||||
}
|
||||
|
||||
/// Replace_copy_if copies elements from the range [first, last) to the range
|
||||
/// [result, result + (last-first)), except that any element for which pred is
|
||||
/// true is not copied; new_value is copied instead. More precisely, for every
|
||||
/// integer n such that 0 <= n < last-first, replace_copy_if performs the
|
||||
/// assignment *(result+n) = new_value if pred(*(first+n)),
|
||||
/// and *(result+n) = *(first+n) otherwise.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename OutputIterator, typename Predicate, typename T>
|
||||
inline OutputIterator replace_copy_if (const Container& ctr, OutputIterator result, Predicate pred, const T& new_value)
|
||||
{
|
||||
return (replace_copy_if (ctr.begin(), ctr.end(), result, pred, new_value));
|
||||
}
|
||||
|
||||
/// Fill assigns the value value to every element in the range [first, last).
|
||||
/// That is, for every iterator i in [first, last),
|
||||
/// it performs the assignment *i = value.
|
||||
/// \ingroup GeneratorAlgorithms
|
||||
///
|
||||
template <typename Container, typename T>
|
||||
inline void fill (Container& ctr, const T& value)
|
||||
{
|
||||
fill (ctr.begin(), ctr.end(), value);
|
||||
}
|
||||
|
||||
/// Generate assigns the result of invoking gen, a function object that
|
||||
/// takes no arguments, to each element in the range [first, last).
|
||||
/// \ingroup GeneratorAlgorithms
|
||||
///
|
||||
template <typename Container, typename Generator>
|
||||
inline void generate (Container& ctr, Generator gen)
|
||||
{
|
||||
generate (ctr.begin(), ctr.end(), gen);
|
||||
}
|
||||
|
||||
/// Randomly permute the elements of the container.
|
||||
/// \ingroup GeneratorAlgorithms
|
||||
///
|
||||
template <typename Container>
|
||||
inline void random_shuffle (Container& ctr)
|
||||
{
|
||||
random_shuffle (ctr.begin(), ctr.end());
|
||||
}
|
||||
|
||||
/// Remove_copy copies elements that are not equal to value from the range
|
||||
/// [first, last) to a range beginning at result. The return value is the
|
||||
/// end of the resulting range. This operation is stable, meaning that the
|
||||
/// relative order of the elements that are copied is the same as in the
|
||||
/// range [first, last).
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename OutputIterator, typename T>
|
||||
inline OutputIterator remove_copy (const Container& ctr, OutputIterator result, const T& value)
|
||||
{
|
||||
return (remove_copy (ctr.begin(), ctr.end(), result, value));
|
||||
}
|
||||
|
||||
/// Remove_copy_if copies elements from the range [first, last) to a range
|
||||
/// beginning at result, except that elements for which pred is true are not
|
||||
/// copied. The return value is the end of the resulting range. This operation
|
||||
/// is stable, meaning that the relative order of the elements that are copied
|
||||
/// is the same as in the range [first, last).
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename OutputIterator, typename Predicate>
|
||||
inline OutputIterator remove_copy_if (const Container& ctr, OutputIterator result, Predicate pred)
|
||||
{
|
||||
return (remove_copy_if (ctr.begin(), ctr.end(), result, pred));
|
||||
}
|
||||
|
||||
/// Remove removes from the range [first, last) all elements that are equal to
|
||||
/// value. That is, remove returns an iterator new_last such that the range
|
||||
/// [first, new_last) contains no elements equal to value. Remove is stable,
|
||||
/// meaning that the relative order of elements that are not equal to value is
|
||||
/// unchanged.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename T>
|
||||
inline void remove (Container& ctr, const T& value)
|
||||
{
|
||||
ctr.erase (remove_copy (ctr.begin(), ctr.end(), ctr.begin(), value), ctr.end());
|
||||
}
|
||||
|
||||
/// Remove removes from the range [first, last) all elements that have an iterator
|
||||
/// in range [rfirst, rlast). The range is assumed to be sorted. That is, remove
|
||||
/// returns an iterator new_last such that the range [first, new_last) contains
|
||||
/// no elements whose iterators are in [rfirst, rlast). Remove is stable,
|
||||
/// meaning that the relative order of elements that are not equal to value is
|
||||
/// unchanged. This version of the algorithm is a uSTL extension.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename ForwardIterator>
|
||||
inline void remove (Container& ctr, ForwardIterator rfirst, ForwardIterator rlast)
|
||||
{
|
||||
ctr.erase (remove_copy (ctr.begin(), ctr.end(), ctr.begin(), rfirst, rlast), ctr.end());
|
||||
}
|
||||
|
||||
/// Remove_if removes from the range [first, last) every element x such that
|
||||
/// pred(x) is true. That is, remove_if returns an iterator new_last such that
|
||||
/// the range [first, new_last) contains no elements for which pred is true.
|
||||
/// The iterators in the range [new_last, last) are all still dereferenceable,
|
||||
/// but the elements that they point to are unspecified. Remove_if is stable,
|
||||
/// meaning that the relative order of elements that are not removed is
|
||||
/// unchanged.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename Predicate>
|
||||
inline void remove_if (Container& ctr, Predicate pred)
|
||||
{
|
||||
ctr.erase (remove_copy_if (ctr.begin(), ctr.end(), ctr.begin(), pred), ctr.end());
|
||||
}
|
||||
|
||||
/// Unique_copy copies elements from the range [first, last) to a range
|
||||
/// beginning with result, except that in a consecutive group of duplicate
|
||||
/// elements only the first one is copied. The return value is the end of
|
||||
/// the range to which the elements are copied. This behavior is similar
|
||||
/// to the Unix filter uniq.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename OutputIterator>
|
||||
inline OutputIterator unique_copy (const Container& ctr, OutputIterator result)
|
||||
{
|
||||
return (unique_copy (ctr.begin(), ctr.end(), result));
|
||||
}
|
||||
|
||||
/// Every time a consecutive group of duplicate elements appears in the range
|
||||
/// [first, last), the algorithm unique removes all but the first element.
|
||||
/// That is, unique returns an iterator new_last such that the range [first,
|
||||
/// new_last) contains no two consecutive elements that are duplicates.
|
||||
/// The iterators in the range [new_last, last) are all still dereferenceable,
|
||||
/// but the elements that they point to are unspecified. Unique is stable,
|
||||
/// meaning that the relative order of elements that are not removed is
|
||||
/// unchanged.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container>
|
||||
inline void unique (Container& ctr)
|
||||
{
|
||||
ctr.erase (unique_copy (ctr.begin(), ctr.end(), ctr.begin()), ctr.end());
|
||||
}
|
||||
|
||||
/// Every time a consecutive group of duplicate elements appears in the range
|
||||
/// [first, last), the algorithm unique removes all but the first element.
|
||||
/// That is, unique returns an iterator new_last such that the range [first,
|
||||
/// new_last) contains no two consecutive elements that are duplicates.
|
||||
/// The iterators in the range [new_last, last) are all still dereferenceable,
|
||||
/// but the elements that they point to are unspecified. Unique is stable,
|
||||
/// meaning that the relative order of elements that are not removed is
|
||||
/// unchanged.
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container, typename BinaryPredicate>
|
||||
inline void unique (Container& ctr, BinaryPredicate binary_pred)
|
||||
{
|
||||
ctr.erase (unique_copy (ctr.begin(), ctr.end(), ctr.begin(), binary_pred), ctr.end());
|
||||
}
|
||||
|
||||
/// Reverse reverses a range.
|
||||
/// That is: for every i such that 0 <= i <= (last - first) / 2),
|
||||
/// it exchanges *(first + i) and *(last - (i + 1)).
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container>
|
||||
inline void reverse (Container& ctr)
|
||||
{
|
||||
reverse (ctr.begin(), ctr.end());
|
||||
}
|
||||
|
||||
/// Exchanges ranges [first, middle) and [middle, last)
|
||||
/// \ingroup MutatingAlgorithms
|
||||
///
|
||||
template <typename Container>
|
||||
inline void rotate (Container& ctr, off_t offset)
|
||||
{
|
||||
assert (size_t(offset > 0 ? offset : -offset) < ctr.size());
|
||||
if (offset > 0)
|
||||
rotate (ctr.begin(), ctr.end() - offset, ctr.end());
|
||||
else
|
||||
rotate (ctr.begin(), ctr.begin() - offset, ctr.end());
|
||||
}
|
||||
|
||||
/// Returns the furthermost iterator i in [first, last) such that,
|
||||
/// for every iterator j in [first, i), *j < value
|
||||
/// Assumes the range is sorted.
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename Container, typename LessThanComparable>
|
||||
inline typename Container::const_iterator lower_bound (const Container& ctr, const LessThanComparable& value)
|
||||
{
|
||||
return (lower_bound (ctr.begin(), ctr.end(), value));
|
||||
}
|
||||
template <typename Container, typename LessThanComparable>
|
||||
inline typename Container::iterator lower_bound (Container& ctr, const LessThanComparable& value)
|
||||
{
|
||||
return (lower_bound (ctr.begin(), ctr.end(), value));
|
||||
}
|
||||
|
||||
/// Returns the furthermost iterator i in [first,last) such that for
|
||||
/// every iterator j in [first,i), value < *j is false.
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename Container, typename LessThanComparable>
|
||||
inline typename Container::const_iterator upper_bound (const Container& ctr, const LessThanComparable& value)
|
||||
{
|
||||
return (upper_bound (ctr.begin(), ctr.end(), value));
|
||||
}
|
||||
template <typename Container, typename LessThanComparable>
|
||||
inline typename Container::iterator upper_bound (Container& ctr, const LessThanComparable& value)
|
||||
{
|
||||
return (upper_bound (ctr.begin(), ctr.end(), value));
|
||||
}
|
||||
|
||||
/// Performs a binary search for \p value.
|
||||
/// Assumes the range is sorted.
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename Container>
|
||||
inline typename Container::const_iterator binary_search (const Container& ctr, const typename Container::value_type& value)
|
||||
{
|
||||
return (binary_search (ctr.begin(), ctr.end(), value));
|
||||
}
|
||||
template <typename Container>
|
||||
inline typename Container::iterator binary_search (Container& ctr, const typename Container::value_type& value)
|
||||
{
|
||||
return (binary_search (ctr.begin(), ctr.end(), value));
|
||||
}
|
||||
|
||||
/// Returns pair<lower_bound,upper_bound>
|
||||
/// \ingroup SearchingAlgorithms
|
||||
///
|
||||
template <typename Container, typename LessThanComparable>
|
||||
inline pair<typename Container::const_iterator,typename Container::const_iterator> equal_range (const Container& ctr, const LessThanComparable& value)
|
||||
{
|
||||
return (equal_range (ctr.begin(), ctr.end(), value));
|
||||
}
|
||||
template <typename Container, typename LessThanComparable>
|
||||
inline pair<typename Container::iterator,typename Container::iterator> equal_range (Container& ctr, const LessThanComparable& value)
|
||||
{
|
||||
return (equal_range (ctr.begin(), ctr.end(), value));
|
||||
}
|
||||
|
||||
/// Sorts the container
|
||||
/// \ingroup SortingAlgorithms
|
||||
///
|
||||
template <typename Container>
|
||||
inline void sort (Container& ctr)
|
||||
{
|
||||
sort (ctr.begin(), ctr.end());
|
||||
}
|
||||
|
||||
/// Sorts the container
|
||||
/// \ingroup SortingAlgorithms
|
||||
///
|
||||
template <typename Container, typename Compare>
|
||||
inline void sort (Container& ctr, Compare comp)
|
||||
{
|
||||
sort (ctr.begin(), ctr.end(), comp);
|
||||
}
|
||||
|
||||
/// Sorts the container
|
||||
/// \ingroup SortingAlgorithms
|
||||
///
|
||||
template <typename Container>
|
||||
inline void stable_sort (Container& ctr)
|
||||
{
|
||||
stable_sort (ctr.begin(), ctr.end());
|
||||
}
|
||||
|
||||
/// Sorts the container
|
||||
/// \ingroup SortingAlgorithms
|
||||
///
|
||||
template <typename Container, typename Compare>
|
||||
inline void stable_sort (Container& ctr, Compare comp)
|
||||
{
|
||||
stable_sort (ctr.begin(), ctr.end(), comp);
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
/// \file uctrstrm.h
|
||||
///
|
||||
/// \brief Serialization templates for standard containers.
|
||||
/// Because containers are templates, a single operator>> is impossible.
|
||||
/// Making virtual read/write is also impossible because not all containers
|
||||
/// contain serializable elements. Therefore, use the macros in this file.
|
||||
///
|
||||
|
||||
#ifndef UCTRSTRM_H_75B2C3EA4980DDDC6B6DFFF767A3B7AC
|
||||
#define UCTRSTRM_H_75B2C3EA4980DDDC6B6DFFF767A3B7AC
|
||||
|
||||
#include "mistream.h"
|
||||
#include "sostream.h"
|
||||
#include "uiosfunc.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Macros for easily declaring a container streamable.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// \brief Declares container template \p type streamable.
|
||||
///
|
||||
/// Use TEMPLATE_TYPE and TEMPLATE_DECL macros to pass in templated
|
||||
/// type with commas and the template declaration.
|
||||
///
|
||||
#define STD_TEMPLATE_CTR_STREAMABLE(type, template_decl) \
|
||||
template_decl \
|
||||
inline istream& operator>> (istream& is, type& v) \
|
||||
{ return (container_read (is, v)); } \
|
||||
template_decl \
|
||||
inline ostream& operator<< (ostream& os, const type& v) \
|
||||
{ return (container_write (os, v)); } \
|
||||
template_decl \
|
||||
inline ostringstream& operator<< (ostringstream& os, const type& v) \
|
||||
{ return (container_text_write (os, v)); } \
|
||||
template_decl \
|
||||
inline size_t stream_size_of (const type& v) \
|
||||
{ return (container_stream_size (v)); }
|
||||
|
||||
/// \brief Declares non-resizable container template \p type streamable.
|
||||
#define STD_TEMPLATE_NR_CTR_STREAMABLE(type, template_decl) \
|
||||
template_decl \
|
||||
inline istream& operator>> (istream& is, type& v) \
|
||||
{ return (nr_container_read (is, v)); } \
|
||||
template_decl \
|
||||
inline ostream& operator<< (ostream& os, const type& v) \
|
||||
{ return (nr_container_write (os, v)); } \
|
||||
template_decl \
|
||||
inline ostringstream& operator<< (ostringstream& os, const type& v) \
|
||||
{ return (container_text_write (os, v)); } \
|
||||
template_decl \
|
||||
inline size_t stream_size_of (const type& v) \
|
||||
{ return (nr_container_stream_size (v)); }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Fixed size container serialization.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// Reads fixed size container \p v from stream \p is.
|
||||
template <typename Container>
|
||||
inline istream& nr_container_read (istream& is, Container& v)
|
||||
{
|
||||
foreach (typename Container::iterator, i, v)
|
||||
is >> *i;
|
||||
return (is);
|
||||
}
|
||||
|
||||
/// Writes fixed size container \p v into stream \p os.
|
||||
template <typename Container>
|
||||
inline ostream& nr_container_write (ostream& os, const Container& v)
|
||||
{
|
||||
foreach (typename Container::const_iterator, i, v)
|
||||
os << *i;
|
||||
return (os);
|
||||
}
|
||||
|
||||
/// Computes the stream size of a fixed size standard container.
|
||||
template <typename Container>
|
||||
size_t nr_container_stream_size (const Container& v)
|
||||
{
|
||||
typedef typename Container::const_iterator vciter_t;
|
||||
typedef typename iterator_traits<vciter_t>::value_type value_type;
|
||||
size_t s = 0;
|
||||
if (numeric_limits<value_type>::is_integral)
|
||||
s += v.size() * stream_size_of(value_type());
|
||||
else
|
||||
foreach (vciter_t, i, v)
|
||||
s += stream_size_of(*i);
|
||||
return (s);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Resizable container serialization.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// Reads container \p v from stream \p is.
|
||||
template <typename Container>
|
||||
istream& container_read (istream& is, Container& v)
|
||||
{
|
||||
typedef typename Container::value_type value_type;
|
||||
typedef typename Container::iterator iterator;
|
||||
typedef typename Container::written_size_type written_size_type;
|
||||
written_size_type n;
|
||||
is >> n;
|
||||
const size_t expectedSize = n * stream_size_of(value_type());
|
||||
#if !PLATFORM_ANDROID
|
||||
is.verify_remaining ("read", typeid(v).name(), expectedSize);
|
||||
#endif
|
||||
if (alignof(value_type()) > alignof(n))
|
||||
is >> ios::talign<value_type>();
|
||||
v.resize (n);
|
||||
nr_container_read (is, v);
|
||||
is >> ios::talign<written_size_type>();
|
||||
return (is);
|
||||
}
|
||||
|
||||
/// Writes the vector to stream \p os.
|
||||
template <typename Container>
|
||||
ostream& container_write (ostream& os, const Container& v)
|
||||
{
|
||||
typedef typename Container::value_type value_type;
|
||||
typedef typename Container::written_size_type written_size_type;
|
||||
const written_size_type sz (v.size());
|
||||
os << sz;
|
||||
if (alignof(value_type()) > alignof(sz))
|
||||
os << ios::talign<value_type>();
|
||||
nr_container_write (os, v);
|
||||
os << ios::talign<written_size_type>();
|
||||
return (os);
|
||||
}
|
||||
|
||||
/// Computes the stream size of a standard container.
|
||||
template <typename Container>
|
||||
size_t container_stream_size (const Container& v)
|
||||
{
|
||||
typedef typename Container::value_type value_type;
|
||||
typedef typename Container::written_size_type written_size_type;
|
||||
const written_size_type sz (v.size());
|
||||
size_t sizeSize = stream_size_of (sz);
|
||||
if (alignof(value_type()) > alignof(sz))
|
||||
sizeSize = Align (sizeSize, alignof(value_type()));
|
||||
return (Align (sizeSize + nr_container_stream_size (v), alignof(sz)));
|
||||
}
|
||||
|
||||
/// \brief Writes element \p v into stream \p os as text.
|
||||
/// Specialize to custom print elements.
|
||||
template <typename T>
|
||||
inline ostringstream& container_element_text_write (ostringstream& os, const T& v)
|
||||
{ return (os << v); }
|
||||
|
||||
/// Writes container \p v into stream \p os as text.
|
||||
template <typename Container>
|
||||
ostringstream& container_text_write (ostringstream& os, const Container& v)
|
||||
{
|
||||
typename Container::const_iterator i = v.begin();
|
||||
os << '(';
|
||||
while (i < v.end()) {
|
||||
container_element_text_write (os, *i);
|
||||
if (++i >= v.end()) break;
|
||||
os << ',';
|
||||
}
|
||||
os << ')';
|
||||
return (os);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,305 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// uexception.cc
|
||||
//
|
||||
|
||||
#include "uassert.h"
|
||||
#include "uexception.h"
|
||||
#include "ustring.h"
|
||||
#include "mistream.h"
|
||||
#include "sostream.h"
|
||||
#include "strmsize.h"
|
||||
#include "uspecial.h"
|
||||
#include <errno.h>
|
||||
#if __GNUC__ >= 3 && !PLATFORM_ANDROID
|
||||
#include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
namespace ustl {
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// \brief Returns a descriptive error message. fmt="%s"
|
||||
/// Overloads of this functions must set NULL as the default fmt
|
||||
/// argument and handle that case to provide a default format string
|
||||
/// in case the user does not have a localized one. The format
|
||||
/// string should be shown in the documentation to not require
|
||||
/// translators to look through code. Also, this function must
|
||||
/// not throw anything, so you must wrap memory allocation routines
|
||||
/// (like string::format, for instance) in a try{}catch(...){} block.
|
||||
///
|
||||
void exception::info (string& msgbuf, const char*) const throw()
|
||||
{
|
||||
#if PLATFORM_ANDROID
|
||||
msgbuf.format ("%s", what());
|
||||
#else /* !PLATFORM_ANDROID */
|
||||
try { msgbuf.format ("%s", what()); } catch (...) { /* Ignore all exceptions */ }
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Reads the exception from stream \p is.
|
||||
void exception::read (istream& is)
|
||||
{
|
||||
uint32_t stmSize;
|
||||
xfmt_t fmt;
|
||||
is >> fmt >> stmSize >> m_Backtrace;
|
||||
assert (fmt == m_Format && "The saved exception is of a different type.");
|
||||
assert (stmSize - exception::stream_size() <= is.remaining() && "The saved exception data is corrupt.");
|
||||
m_Format = fmt;
|
||||
}
|
||||
|
||||
/// Writes the exception into stream \p os as an IFF chunk.
|
||||
void exception::write (ostream& os) const
|
||||
{
|
||||
os << m_Format << uint32_t(stream_size()) << m_Backtrace;
|
||||
}
|
||||
|
||||
/// Writes the exception as text into stream \p os.
|
||||
void exception::text_write (ostringstream& os) const
|
||||
{
|
||||
#if !PLATFORM_ANDROID
|
||||
try {
|
||||
#endif
|
||||
string buf;
|
||||
info (buf);
|
||||
os << buf;
|
||||
#if !PLATFORM_ANDROID
|
||||
} catch (...) {}
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// Initializes the empty object. \p nBytes is the size of the attempted allocation.
|
||||
bad_alloc::bad_alloc (size_t nBytes) throw()
|
||||
: ustl::exception(),
|
||||
m_nBytesRequested (nBytes)
|
||||
{
|
||||
set_format (xfmt_BadAlloc);
|
||||
}
|
||||
|
||||
/// Returns a descriptive error message. fmt="failed to allocate %d bytes"
|
||||
void bad_alloc::info (string& msgbuf, const char* fmt) const throw()
|
||||
{
|
||||
if (!fmt) fmt = "failed to allocate %d bytes";
|
||||
#if PLATFORM_ANDROID
|
||||
msgbuf.format (fmt, m_nBytesRequested);
|
||||
#else /* !PLATFORM_ANDROID */
|
||||
try { msgbuf.format (fmt, m_nBytesRequested); } catch (...) {}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Reads the exception from stream \p is.
|
||||
void bad_alloc::read (istream& is)
|
||||
{
|
||||
ustl::exception::read (is);
|
||||
is >> m_nBytesRequested;
|
||||
}
|
||||
|
||||
/// Writes the exception into stream \p os.
|
||||
void bad_alloc::write (ostream& os) const
|
||||
{
|
||||
ustl::exception::write (os);
|
||||
os << m_nBytesRequested;
|
||||
}
|
||||
|
||||
/// Returns the size of the written exception.
|
||||
size_t bad_alloc::stream_size (void) const
|
||||
{
|
||||
return (ustl::exception::stream_size() + stream_size_of(m_nBytesRequested));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// Initializes the empty object. \p operation is the function that returned the error code.
|
||||
libc_exception::libc_exception (const char* operation) throw()
|
||||
: exception(),
|
||||
m_Errno (errno),
|
||||
m_Operation (operation)
|
||||
{
|
||||
set_format (xfmt_LibcException);
|
||||
}
|
||||
|
||||
/// Copies object \p v.
|
||||
libc_exception::libc_exception (const libc_exception& v) throw()
|
||||
: exception (v),
|
||||
m_Errno (v.m_Errno),
|
||||
m_Operation (v.m_Operation)
|
||||
{
|
||||
}
|
||||
|
||||
/// Copies object \p v.
|
||||
const libc_exception& libc_exception::operator= (const libc_exception& v)
|
||||
{
|
||||
m_Errno = v.m_Errno;
|
||||
m_Operation = v.m_Operation;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
/// Returns a descriptive error message. fmt="%s: %m"
|
||||
void libc_exception::info (string& msgbuf, const char* fmt) const throw()
|
||||
{
|
||||
if (!fmt) fmt = "%s: %m";
|
||||
#if PLATFORM_ANDROID
|
||||
msgbuf.format (fmt, m_Operation, m_Errno, m_Errno);
|
||||
#else /* !PLATFORM_ANDROID */
|
||||
try { msgbuf.format (fmt, m_Operation, m_Errno, m_Errno); } catch (...) {}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Reads the exception from stream \p is.
|
||||
void libc_exception::read (istream& is)
|
||||
{
|
||||
exception::read (is);
|
||||
is >> m_Errno >> m_Operation;
|
||||
}
|
||||
|
||||
/// Writes the exception into stream \p os.
|
||||
void libc_exception::write (ostream& os) const
|
||||
{
|
||||
exception::write (os);
|
||||
os << m_Errno << m_Operation;
|
||||
}
|
||||
|
||||
/// Returns the size of the written exception.
|
||||
size_t libc_exception::stream_size (void) const
|
||||
{
|
||||
return (exception::stream_size() +
|
||||
stream_size_of(m_Errno) +
|
||||
stream_size_of(m_Operation));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// Initializes the empty object. \p operation is the function that returned the error code.
|
||||
file_exception::file_exception (const char* operation, const char* filename) throw()
|
||||
: libc_exception (operation)
|
||||
{
|
||||
memset (m_Filename, 0, VectorSize(m_Filename));
|
||||
set_format (xfmt_FileException);
|
||||
if (filename) {
|
||||
strncpy (m_Filename, filename, VectorSize(m_Filename));
|
||||
m_Filename [VectorSize(m_Filename) - 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a descriptive error message. fmt="%s %s: %m"
|
||||
void file_exception::info (string& msgbuf, const char* fmt) const throw()
|
||||
{
|
||||
if (!fmt) fmt = "%s %s: %m";
|
||||
#if PLATFORM_ANDROID
|
||||
msgbuf.format (fmt, m_Operation, m_Filename, m_Errno, m_Errno);
|
||||
#else /* !PLATFORM_ANDROID */
|
||||
try { msgbuf.format (fmt, m_Operation, m_Filename, m_Errno, m_Errno); } catch (...) {}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Reads the exception from stream \p is.
|
||||
void file_exception::read (istream& is)
|
||||
{
|
||||
libc_exception::read (is);
|
||||
string filename;
|
||||
is >> filename;
|
||||
is.align (8);
|
||||
filename.copyto (filename, VectorSize(m_Filename));
|
||||
}
|
||||
|
||||
/// Writes the exception into stream \p os.
|
||||
void file_exception::write (ostream& os) const
|
||||
{
|
||||
libc_exception::write (os);
|
||||
os << string (m_Filename);
|
||||
os.align (8);
|
||||
}
|
||||
|
||||
/// Returns the size of the written exception.
|
||||
size_t file_exception::stream_size (void) const
|
||||
{
|
||||
return (libc_exception::stream_size() +
|
||||
Align (stream_size_of (string (m_Filename)), 8));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// \brief Uses C++ ABI call, if available to demangle the contents of \p buf.
|
||||
///
|
||||
/// The result is written to \p buf, with the maximum size of \p bufSize, and
|
||||
/// is zero-terminated. The return value is \p buf.
|
||||
///
|
||||
const char* demangle_type_name (char* buf, size_t bufSize, size_t* pdmSize)
|
||||
{
|
||||
size_t bl = strlen (buf);
|
||||
#if __GNUC__ >= 3 && !PLATFORM_ANDROID
|
||||
char dmname [256];
|
||||
size_t sz = VectorSize(dmname);
|
||||
int bFailed;
|
||||
abi::__cxa_demangle (buf, dmname, &sz, &bFailed);
|
||||
if (!bFailed) {
|
||||
bl = min (strlen (dmname), bufSize - 1);
|
||||
memcpy (buf, dmname, bl);
|
||||
buf[bl] = 0;
|
||||
}
|
||||
#else
|
||||
bl = min (bl, bufSize);
|
||||
#endif
|
||||
if (pdmSize)
|
||||
*pdmSize = bl;
|
||||
return (buf);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// Initializes the empty object. \p operation is the function that returned the error code.
|
||||
stream_bounds_exception::stream_bounds_exception (const char* operation, const char* type, uoff_t offset, size_t expected, size_t remaining) throw()
|
||||
: libc_exception (operation),
|
||||
m_TypeName (type),
|
||||
m_Offset (offset),
|
||||
m_Expected (expected),
|
||||
m_Remaining (remaining)
|
||||
{
|
||||
set_format (xfmt_StreamBoundsException);
|
||||
}
|
||||
|
||||
/// Returns a descriptive error message. fmt="%s stream %s: @%u: expected %u, available %u";
|
||||
void stream_bounds_exception::info (string& msgbuf, const char* fmt) const throw()
|
||||
{
|
||||
char typeName [256];
|
||||
strncpy (typeName, m_TypeName, VectorSize(typeName));
|
||||
typeName[VectorSize(typeName)-1] = 0;
|
||||
if (!fmt) fmt = "%s stream %s: @0x%X: need %u bytes, have %u";
|
||||
#if PLATFORM_ANDROID
|
||||
msgbuf.format (fmt, demangle_type_name (VectorBlock(typeName)), m_Operation, m_Offset, m_Expected, m_Remaining);
|
||||
#else /* !PLATFORM_ANDROID */
|
||||
try { msgbuf.format (fmt, demangle_type_name (VectorBlock(typeName)), m_Operation, m_Offset, m_Expected, m_Remaining); } catch (...) {}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Reads the exception from stream \p is.
|
||||
void stream_bounds_exception::read (istream& is)
|
||||
{
|
||||
libc_exception::read (is);
|
||||
is >> m_TypeName >> m_Offset >> m_Expected >> m_Remaining;
|
||||
}
|
||||
|
||||
/// Writes the exception into stream \p os.
|
||||
void stream_bounds_exception::write (ostream& os) const
|
||||
{
|
||||
libc_exception::write (os);
|
||||
os << m_TypeName << m_Offset << m_Expected << m_Remaining;
|
||||
}
|
||||
|
||||
/// Returns the size of the written exception.
|
||||
size_t stream_bounds_exception::stream_size (void) const
|
||||
{
|
||||
return (libc_exception::stream_size() +
|
||||
stream_size_of(m_TypeName) +
|
||||
stream_size_of(m_Offset) +
|
||||
stream_size_of(m_Expected) +
|
||||
stream_size_of(m_Remaining));
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// uexception.h
|
||||
//
|
||||
// This file contains stuff from \<exception\>.
|
||||
// The standard C++ headers are duplicated because uSTL is intended
|
||||
// to completely replace all C++ standard library functions.
|
||||
//
|
||||
|
||||
#ifndef UEXCEPTION_H_18DE3EF55C4F00673268F0D66546AF5D
|
||||
#define UEXCEPTION_H_18DE3EF55C4F00673268F0D66546AF5D
|
||||
|
||||
#include "utypes.h"
|
||||
#ifndef WITHOUT_LIBSTDCPP
|
||||
#include <exception>
|
||||
#include <new>
|
||||
#endif
|
||||
#include "bktrace.h"
|
||||
|
||||
#ifdef WITHOUT_LIBSTDCPP // This code is copied from <exception>
|
||||
namespace std {
|
||||
/// If you write a replacement terminate handler, it must be of this type.
|
||||
typedef void (*terminate_handler) (void);
|
||||
/// If you write a replacement unexpected handler, it must be of this type.
|
||||
typedef void (*unexpected_handler) (void);
|
||||
/// Takes a new handler function as an argument, returns the old function.
|
||||
terminate_handler set_terminate (terminate_handler pHandler) throw();
|
||||
/// The runtime will call this function if exception handling must be
|
||||
/// abandoned for any reason. It can also be called by the user.
|
||||
void terminate (void) __attribute__ ((__noreturn__));
|
||||
/// Takes a new handler function as an argument, returns the old function.
|
||||
unexpected_handler set_unexpected (unexpected_handler pHandler) throw();
|
||||
/// The runtime will call this function if an exception is thrown which
|
||||
/// violates the function's exception specification.
|
||||
void unexpected (void) __attribute__ ((__noreturn__));
|
||||
/// Returns true when the caught exception violates the throw specification.
|
||||
bool uncaught_exception() throw();
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
namespace ustl {
|
||||
|
||||
class string;
|
||||
|
||||
typedef uint32_t xfmt_t;
|
||||
|
||||
enum {
|
||||
xfmt_Exception,
|
||||
xfmt_BadAlloc,
|
||||
xfmt_LibcException = 12,
|
||||
xfmt_FileException = 13,
|
||||
xfmt_StreamBoundsException = 14
|
||||
};
|
||||
|
||||
/// \class exception uexception.h ustl.h
|
||||
/// \ingroup Exceptions
|
||||
///
|
||||
/// \brief Base class for exceptions, equivalent to std::exception.
|
||||
///
|
||||
#ifdef WITHOUT_LIBSTDCPP
|
||||
class exception {
|
||||
#else
|
||||
class exception : public std::exception {
|
||||
#endif
|
||||
public:
|
||||
typedef const CBacktrace& rcbktrace_t;
|
||||
public:
|
||||
inline exception (void) throw() : m_Format (xfmt_Exception) {}
|
||||
inline virtual ~exception (void) throw() {}
|
||||
inline virtual const char* what (void) const throw() { return ("error"); }
|
||||
virtual void info (string& msgbuf, const char* fmt = NULL) const throw();
|
||||
virtual void read (istream& is);
|
||||
virtual void write (ostream& os) const;
|
||||
void text_write (ostringstream& os) const;
|
||||
inline virtual size_t stream_size (void) const { return (sizeof(m_Format) + sizeof(uint32_t) + m_Backtrace.stream_size()); }
|
||||
/// Format of the exception is used to lookup exception::info format string.
|
||||
/// Another common use is the instantiation of serialized exceptions, used
|
||||
/// by the error handler node chain to troubleshoot specific errors.
|
||||
inline xfmt_t format (void) const { return (m_Format); }
|
||||
inline rcbktrace_t backtrace (void) const { return (m_Backtrace); }
|
||||
protected:
|
||||
inline void set_format (xfmt_t fmt) { m_Format = fmt; }
|
||||
private:
|
||||
CBacktrace m_Backtrace; ///< Backtrace of the throw point.
|
||||
xfmt_t m_Format; ///< Format of the exception's data.
|
||||
};
|
||||
|
||||
/// \class bad_cast uexception.h ustl.h
|
||||
/// \ingroup Exceptions
|
||||
///
|
||||
/// \brief Thrown to indicate a bad dynamic_cast usage.
|
||||
///
|
||||
class bad_cast : public exception {
|
||||
public:
|
||||
inline explicit bad_cast (void) throw() : exception() {}
|
||||
inline virtual const char* what (void) const throw() { return ("bad cast"); }
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// \class bad_alloc uexception.h ustl.h
|
||||
/// \ingroup Exceptions
|
||||
///
|
||||
/// \brief Exception thrown on memory allocation failure by memblock::reserve.
|
||||
///
|
||||
#ifdef WITHOUT_LIBSTDCPP
|
||||
class bad_alloc : public exception {
|
||||
#else
|
||||
class bad_alloc : public std::bad_alloc, public exception {
|
||||
#endif
|
||||
public:
|
||||
explicit bad_alloc (size_t nBytes = 0) throw();
|
||||
inline virtual const char* what (void) const throw() { return ("memory allocation failed"); }
|
||||
virtual void info (string& msgbuf, const char* fmt = NULL) const throw();
|
||||
virtual void read (istream& is);
|
||||
virtual void write (ostream& os) const;
|
||||
virtual size_t stream_size (void) const;
|
||||
protected:
|
||||
size_t m_nBytesRequested; ///< Number of bytes requested by the failed allocation.
|
||||
};
|
||||
|
||||
/// \class libc_exception uexception.h ustl.h
|
||||
/// \ingroup Exceptions
|
||||
///
|
||||
/// \brief Thrown when a libc function returns an error.
|
||||
///
|
||||
/// Contains an errno and description. This is a uSTL extension.
|
||||
///
|
||||
class libc_exception : public exception {
|
||||
public:
|
||||
explicit libc_exception (const char* operation) throw();
|
||||
libc_exception (const libc_exception& v) throw();
|
||||
const libc_exception& operator= (const libc_exception& v);
|
||||
inline virtual const char* what (void) const throw() { return ("libc function failed"); }
|
||||
virtual void info (string& msgbuf, const char* fmt = NULL) const throw();
|
||||
virtual void read (istream& is);
|
||||
virtual void write (ostream& os) const;
|
||||
virtual size_t stream_size (void) const;
|
||||
protected:
|
||||
intptr_t m_Errno; ///< Error code returned by the failed operation.
|
||||
const char* m_Operation; ///< Name of the failed operation.
|
||||
};
|
||||
|
||||
/// \class file_exception uexception.h ustl.h
|
||||
/// \ingroup Exceptions
|
||||
///
|
||||
/// \brief File-related exceptions.
|
||||
///
|
||||
/// Contains the file name. This is a uSTL extension.
|
||||
///
|
||||
class file_exception : public libc_exception {
|
||||
public:
|
||||
file_exception (const char* operation, const char* filename) throw();
|
||||
inline virtual const char* what (void) const throw() { return ("file error"); }
|
||||
virtual void info (string& msgbuf, const char* fmt = NULL) const throw();
|
||||
virtual void read (istream& is);
|
||||
virtual void write (ostream& os) const;
|
||||
virtual size_t stream_size (void) const;
|
||||
protected:
|
||||
char m_Filename [PATH_MAX]; ///< Name of the file causing the error.
|
||||
};
|
||||
|
||||
/// \class stream_bounds_exception uexception.h ustl.h
|
||||
/// \ingroup Exceptions
|
||||
///
|
||||
/// \brief Stream bounds checking.
|
||||
///
|
||||
/// Only thrown in debug builds unless you say otherwise in config.h
|
||||
/// This is a uSTL extension.
|
||||
///
|
||||
class stream_bounds_exception : public libc_exception {
|
||||
public:
|
||||
stream_bounds_exception (const char* operation, const char* type, uoff_t offset, size_t expected, size_t remaining) throw();
|
||||
inline virtual const char* what (void) const throw() { return ("stream bounds exception"); }
|
||||
virtual void info (string& msgbuf, const char* fmt = NULL) const throw();
|
||||
virtual void read (istream& is);
|
||||
virtual void write (ostream& os) const;
|
||||
virtual size_t stream_size (void) const;
|
||||
protected:
|
||||
const char* m_TypeName;
|
||||
uoff_t m_Offset;
|
||||
size_t m_Expected;
|
||||
size_t m_Remaining;
|
||||
};
|
||||
|
||||
const char* demangle_type_name (char* buf, size_t bufSize, size_t* pdmSize = NULL);
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,480 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// \file ufunction.h
|
||||
//
|
||||
// \brief Implements STL standard functors.
|
||||
//
|
||||
// See STL specification and bvts for usage of these. The only
|
||||
// extension is the mem_var functors for member variable access:
|
||||
// \code
|
||||
// f = find_if (ctr, mem_var_equal_to(&MyClass::m_Var, matchVar));
|
||||
// f = find_if (ctr, mem_var_less(&MyClass::m_Var, matchVar));
|
||||
// \endcode
|
||||
// There are a couple of others but the syntax is much harder to grasp.
|
||||
// See bvt10.cc for more examples.
|
||||
//
|
||||
|
||||
#ifndef UFUNCTION_H_221ABA8551801799263C927234C085F3
|
||||
#define UFUNCTION_H_221ABA8551801799263C927234C085F3
|
||||
|
||||
namespace ustl {
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Standard functors
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// \brief void-returning function abstract interface.
|
||||
/// \ingroup FunctorObjects
|
||||
template <typename Result>
|
||||
struct void_function {
|
||||
typedef Result result_type;
|
||||
};
|
||||
|
||||
/// \brief \p Result f (\p Arg) function abstract interface.
|
||||
/// \ingroup FunctorObjects
|
||||
template <typename Arg, typename Result>
|
||||
struct unary_function {
|
||||
typedef Arg argument_type;
|
||||
typedef Result result_type;
|
||||
};
|
||||
|
||||
/// \brief \p Result f (\p Arg1, \p Arg2) function abstract interface.
|
||||
/// \ingroup FunctorObjects
|
||||
template <typename Arg1, typename Arg2, typename Result>
|
||||
struct binary_function {
|
||||
typedef Arg1 first_argument_type;
|
||||
typedef Arg2 second_argument_type;
|
||||
typedef Result result_type;
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
#define STD_BINARY_FUNCTOR(name, rv, func) \
|
||||
template <class T> struct name : public binary_function<T,T,rv> \
|
||||
{ inline rv operator()(const T& a, const T& b) const { return func; } };
|
||||
#define STD_UNARY_FUNCTOR(name, rv, func) \
|
||||
template <class T> struct name : public unary_function<T,rv> \
|
||||
{ inline rv operator()(const T& a) const { return func; } };
|
||||
#define STD_CONVERSION_FUNCTOR(name, func) \
|
||||
template <class S, class D> struct name : public unary_function<S,D> \
|
||||
{ inline D operator()(const S& a) const { return func; } };
|
||||
|
||||
STD_BINARY_FUNCTOR (plus, T, (a + b))
|
||||
STD_BINARY_FUNCTOR (minus, T, (a - b))
|
||||
STD_BINARY_FUNCTOR (divides, T, (a / b))
|
||||
STD_BINARY_FUNCTOR (modulus, T, (a % b))
|
||||
STD_BINARY_FUNCTOR (multiplies, T, (a * b))
|
||||
STD_BINARY_FUNCTOR (logical_and, T, (a && b))
|
||||
STD_BINARY_FUNCTOR (logical_or, T, (a || b))
|
||||
STD_UNARY_FUNCTOR (logical_not, T, (!a))
|
||||
STD_BINARY_FUNCTOR (bitwise_or, T, (a | b))
|
||||
STD_BINARY_FUNCTOR (bitwise_and, T, (a & b))
|
||||
STD_BINARY_FUNCTOR (bitwise_xor, T, (a ^ b))
|
||||
STD_UNARY_FUNCTOR (bitwise_not, T, (~a))
|
||||
STD_UNARY_FUNCTOR (negate, T, (-a))
|
||||
STD_BINARY_FUNCTOR (equal_to, bool, (a == b))
|
||||
STD_BINARY_FUNCTOR (not_equal_to, bool, (!(a == b)))
|
||||
STD_BINARY_FUNCTOR (greater, bool, (b < a))
|
||||
STD_BINARY_FUNCTOR (less, bool, (a < b))
|
||||
STD_BINARY_FUNCTOR (greater_equal, bool, (!(a < b)))
|
||||
STD_BINARY_FUNCTOR (less_equal, bool, (!(b < a)))
|
||||
STD_BINARY_FUNCTOR (compare, int, (a < b ? -1 : (b < a)))
|
||||
STD_UNARY_FUNCTOR (identity, T, (a))
|
||||
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
/// \brief Selects and returns the first argument.
|
||||
/// \ingroup FunctorObjects
|
||||
template <class T1, class T2> struct project1st : public binary_function<T1,T2,T1> { inline const T1& operator()(const T1& a, const T2&) const { return (a); } };
|
||||
/// \brief Selects and returns the second argument.
|
||||
/// \ingroup FunctorObjects
|
||||
template <class T1, class T2> struct project2nd : public binary_function<T1,T2,T2> { inline const T2& operator()(const T1&, const T2& a) const { return (a); } };
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Generic function to functor converters.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// \brief Wrapper object for unary function pointers.
|
||||
/// Use the \ref ptr_fun accessor to create this object.
|
||||
/// \ingroup FunctorObjects
|
||||
template <typename Arg, typename Result>
|
||||
class pointer_to_unary_function : public unary_function<Arg,Result> {
|
||||
public:
|
||||
typedef Arg argument_type;
|
||||
typedef Result result_type;
|
||||
typedef Result (*pfunc_t)(Arg);
|
||||
public:
|
||||
explicit inline pointer_to_unary_function (pfunc_t pfn) : m_pfn (pfn) {}
|
||||
inline result_type operator() (argument_type v) const { return (m_pfn(v)); }
|
||||
private:
|
||||
pfunc_t m_pfn; ///< Pointer to the wrapped function.
|
||||
};
|
||||
|
||||
/// \brief Wrapper object for binary function pointers.
|
||||
/// Use the \ref ptr_fun accessor to create this object.
|
||||
/// \ingroup FunctorObjects
|
||||
template <typename Arg1, typename Arg2, typename Result>
|
||||
class pointer_to_binary_function : public binary_function<Arg1,Arg2,Result> {
|
||||
public:
|
||||
typedef Arg1 first_argument_type;
|
||||
typedef Arg2 second_argument_type;
|
||||
typedef Result result_type;
|
||||
typedef Result (*pfunc_t)(Arg1, Arg2);
|
||||
public:
|
||||
explicit inline pointer_to_binary_function (pfunc_t pfn) : m_pfn (pfn) {}
|
||||
inline result_type operator() (first_argument_type v1, second_argument_type v2) const { return (m_pfn(v1, v2)); }
|
||||
private:
|
||||
pfunc_t m_pfn; ///< Pointer to the wrapped function.
|
||||
};
|
||||
|
||||
/// ptr_fun(pfn) wraps function pointer pfn into a functor class that calls it.
|
||||
/// \ingroup FunctorAccessors
|
||||
template <typename Arg, typename Result>
|
||||
inline pointer_to_unary_function<Arg,Result> ptr_fun (Result (*pfn)(Arg))
|
||||
{
|
||||
return (pointer_to_unary_function<Arg,Result> (pfn));
|
||||
}
|
||||
|
||||
/// ptr_fun(pfn) wraps function pointer pfn into a functor class that calls it.
|
||||
/// \ingroup FunctorAccessors
|
||||
template <typename Arg1, typename Arg2, typename Result>
|
||||
inline pointer_to_binary_function<Arg1,Arg2,Result> ptr_fun (Result (*pfn)(Arg1,Arg2))
|
||||
{
|
||||
return (pointer_to_binary_function<Arg1,Arg2,Result> (pfn));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Negators.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// \brief Wraps a unary function to return its logical negative.
|
||||
/// Use the \ref unary_negator accessor to create this object.
|
||||
/// \ingroup FunctorObjects
|
||||
template <class UnaryFunction>
|
||||
class unary_negate : public unary_function<typename UnaryFunction::argument_type,
|
||||
typename UnaryFunction::result_type> {
|
||||
public:
|
||||
typedef typename UnaryFunction::argument_type argument_type;
|
||||
typedef typename UnaryFunction::result_type result_type;
|
||||
public:
|
||||
explicit inline unary_negate (UnaryFunction pfn) : m_pfn (pfn) {}
|
||||
inline result_type operator() (argument_type v) const { return (!m_pfn(v)); }
|
||||
private:
|
||||
UnaryFunction m_pfn;
|
||||
};
|
||||
|
||||
/// Returns the functor that negates the result of *pfn().
|
||||
/// \ingroup FunctorAccessors
|
||||
template <class UnaryFunction>
|
||||
inline unary_negate<UnaryFunction> unary_negator (UnaryFunction pfn)
|
||||
{
|
||||
return (unary_negate<UnaryFunction>(pfn));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Argument binders
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// \brief Converts a binary function to a unary function
|
||||
/// by binding a constant value to the first argument.
|
||||
/// Use the \ref bind1st accessor to create this object.
|
||||
/// \ingroup FunctorObjects
|
||||
template <class BinaryFunction>
|
||||
class binder1st : public unary_function<typename BinaryFunction::second_argument_type,
|
||||
typename BinaryFunction::result_type> {
|
||||
public:
|
||||
typedef typename BinaryFunction::first_argument_type arg1_t;
|
||||
typedef typename BinaryFunction::second_argument_type arg2_t;
|
||||
typedef typename BinaryFunction::result_type result_t;
|
||||
public:
|
||||
inline binder1st (const BinaryFunction& pfn, const arg1_t& v) : m_pfn (pfn), m_Value(v) {}
|
||||
inline result_t operator()(arg2_t v2) const { return (m_pfn (m_Value, v2)); }
|
||||
protected:
|
||||
BinaryFunction m_pfn;
|
||||
arg1_t m_Value;
|
||||
};
|
||||
|
||||
/// \brief Converts a binary function to a unary function
|
||||
/// by binding a constant value to the second argument.
|
||||
/// Use the \ref bind2nd accessor to create this object.
|
||||
/// \ingroup FunctorObjects
|
||||
template <class BinaryFunction>
|
||||
class binder2nd : public unary_function<typename BinaryFunction::first_argument_type,
|
||||
typename BinaryFunction::result_type> {
|
||||
public:
|
||||
typedef typename BinaryFunction::first_argument_type arg1_t;
|
||||
typedef typename BinaryFunction::second_argument_type arg2_t;
|
||||
typedef typename BinaryFunction::result_type result_t;
|
||||
public:
|
||||
inline binder2nd (const BinaryFunction& pfn, const arg2_t& v) : m_pfn (pfn), m_Value(v) {}
|
||||
inline result_t operator()(arg1_t v1) const { return (m_pfn (v1, m_Value)); }
|
||||
protected:
|
||||
BinaryFunction m_pfn;
|
||||
arg2_t m_Value;
|
||||
};
|
||||
|
||||
/// Converts \p pfn into a unary function by binding the first argument to \p v.
|
||||
/// \ingroup FunctorAccessors
|
||||
template <typename BinaryFunction>
|
||||
inline binder1st<BinaryFunction>
|
||||
bind1st (BinaryFunction pfn, typename BinaryFunction::first_argument_type v)
|
||||
{
|
||||
return (binder1st<BinaryFunction> (pfn, v));
|
||||
}
|
||||
|
||||
/// Converts \p pfn into a unary function by binding the second argument to \p v.
|
||||
/// \ingroup FunctorAccessors
|
||||
template <typename BinaryFunction>
|
||||
inline binder2nd<BinaryFunction>
|
||||
bind2nd (BinaryFunction pfn, typename BinaryFunction::second_argument_type v)
|
||||
{
|
||||
return (binder2nd<BinaryFunction> (pfn, v));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Composition adapters
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// \brief Chains two unary functions together.
|
||||
///
|
||||
/// When f(x) and g(x) are composed, the result is function c(x)=f(g(x)).
|
||||
/// Use the \ref compose1 accessor to create this object.
|
||||
/// This template is an extension, implemented by SGI STL and uSTL.
|
||||
/// \ingroup FunctorObjects
|
||||
///
|
||||
template <typename Operation1, typename Operation2>
|
||||
class unary_compose : public unary_function<typename Operation2::argument_type,
|
||||
typename Operation1::result_type> {
|
||||
public:
|
||||
typedef typename Operation2::argument_type arg_t;
|
||||
typedef const arg_t& rcarg_t;
|
||||
typedef typename Operation1::result_type result_t;
|
||||
public:
|
||||
inline unary_compose (const Operation1& f, const Operation2& g) : m_f(f), m_g(g) {}
|
||||
inline result_t operator() (rcarg_t x) const { return m_f(m_g(x)); }
|
||||
protected:
|
||||
Operation1 m_f; ///< f(x), if c(x) = f(g(x))
|
||||
Operation2 m_g; ///< g(x), if c(x) = f(g(x))
|
||||
};
|
||||
|
||||
/// Creates a \ref unary_compose object whose function c(x)=f(g(x))
|
||||
/// \ingroup FunctorAccessors
|
||||
template <typename Operation1, typename Operation2>
|
||||
inline unary_compose<Operation1, Operation2>
|
||||
compose1 (const Operation1& f, const Operation2& g)
|
||||
{ return unary_compose<Operation1,Operation2>(f, g); }
|
||||
|
||||
/// \brief Chains two unary functions through a binary function.
|
||||
///
|
||||
/// When f(x,y), g(x), and h(x) are composed, the result is function
|
||||
/// c(x)=f(g(x),h(x)). Use the \ref compose2 accessor to create this
|
||||
/// object. This template is an extension, implemented by SGI STL and uSTL.
|
||||
/// \ingroup FunctorObjects
|
||||
///
|
||||
template <typename Operation1, typename Operation2, typename Operation3>
|
||||
class binary_compose : public unary_function<typename Operation2::argument_type,
|
||||
typename Operation1::result_type> {
|
||||
public:
|
||||
typedef typename Operation2::argument_type arg_t;
|
||||
typedef const arg_t& rcarg_t;
|
||||
typedef typename Operation1::result_type result_t;
|
||||
public:
|
||||
inline binary_compose (const Operation1& f, const Operation2& g, const Operation3& h) : m_f(f), m_g(g), m_h(h) {}
|
||||
inline result_t operator() (rcarg_t x) const { return m_f(m_g(x), m_h(x)); }
|
||||
protected:
|
||||
Operation1 m_f; ///< f(x,y), if c(x) = f(g(x),h(x))
|
||||
Operation2 m_g; ///< g(x), if c(x) = f(g(x),h(x))
|
||||
Operation3 m_h; ///< h(x), if c(x) = f(g(x),h(x))
|
||||
};
|
||||
|
||||
/// Creates a \ref binary_compose object whose function c(x)=f(g(x),h(x))
|
||||
/// \ingroup FunctorAccessors
|
||||
template <typename Operation1, typename Operation2, typename Operation3>
|
||||
inline binary_compose<Operation1, Operation2, Operation3>
|
||||
compose2 (const Operation1& f, const Operation2& g, const Operation3& h)
|
||||
{ return binary_compose<Operation1, Operation2, Operation3> (f, g, h); }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Member function adaptors
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
#define MEM_FUN_T(WrapperName, ClassName, ArgType, FuncType, CallType) \
|
||||
template <typename Ret, class T> \
|
||||
class ClassName : public unary_function<ArgType,Ret> { \
|
||||
public: \
|
||||
typedef Ret (T::*func_t) FuncType; \
|
||||
public: \
|
||||
explicit inline ClassName (func_t pf) : m_pf (pf) {} \
|
||||
inline Ret operator() (ArgType p) const { return ((p CallType m_pf)()); } \
|
||||
private: \
|
||||
func_t m_pf; \
|
||||
}; \
|
||||
\
|
||||
template <class Ret, typename T> \
|
||||
inline ClassName<Ret,T> WrapperName (Ret (T::*pf) FuncType) \
|
||||
{ \
|
||||
return (ClassName<Ret,T> (pf)); \
|
||||
}
|
||||
|
||||
MEM_FUN_T(mem_fun, mem_fun_t, T*, (void), ->*)
|
||||
MEM_FUN_T(mem_fun, const_mem_fun_t, const T*, (void) const, ->*)
|
||||
MEM_FUN_T(mem_fun_ref, mem_fun_ref_t, T&, (void), .*)
|
||||
MEM_FUN_T(mem_fun_ref, const_mem_fun_ref_t, const T&, (void) const, .*)
|
||||
|
||||
#define EXT_MEM_FUN_T(ClassName, HostType, FuncType) \
|
||||
template <class T, typename Ret, typename V> \
|
||||
class ClassName : public unary_function<V,void> { \
|
||||
public: \
|
||||
typedef Ret (T::*func_t)(V) FuncType; \
|
||||
public: \
|
||||
inline ClassName (HostType t, func_t pf) : m_t (t), m_pf (pf) {} \
|
||||
inline Ret operator() (V v) const { return ((m_t->*m_pf)(v)); } \
|
||||
private: \
|
||||
HostType m_t; \
|
||||
func_t m_pf; \
|
||||
}; \
|
||||
\
|
||||
template <class T, typename Ret, typename V> \
|
||||
inline ClassName<T,Ret,V> mem_fun (HostType p, Ret (T::*pf)(V) FuncType) \
|
||||
{ \
|
||||
return (ClassName<T,Ret,V> (p, pf)); \
|
||||
}
|
||||
|
||||
EXT_MEM_FUN_T(ext_mem_fun_t, T*, )
|
||||
EXT_MEM_FUN_T(const_ext_mem_fun_t, const T*, const)
|
||||
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Member variable adaptors (uSTL extension)
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
#define MEM_VAR_T(FunctorName, ArgType, VarType, BaseClass, CallImpl) \
|
||||
template <typename Function, class T, typename VT> \
|
||||
class FunctorName##_t : public BaseClass { \
|
||||
public: \
|
||||
typedef ArgType argument_type; \
|
||||
typedef typename Function::result_type result_type; \
|
||||
typedef VarType mem_var_ptr_t; \
|
||||
public: \
|
||||
inline FunctorName##_t (mem_var_ptr_t pv, Function pfn) : m_pv(pv), m_pfn(pfn) {} \
|
||||
inline result_type operator() CallImpl \
|
||||
private: \
|
||||
mem_var_ptr_t m_pv; \
|
||||
Function m_pfn; \
|
||||
}; \
|
||||
\
|
||||
template <typename Function, class T, typename VT> \
|
||||
inline FunctorName##_t<Function, T, VT> \
|
||||
FunctorName (VT T::*mvp, Function pfn) \
|
||||
{ \
|
||||
return (FunctorName##_t<Function,T,VT> (mvp, pfn)); \
|
||||
}
|
||||
|
||||
#define FUNCTOR_UNARY_BASE(ArgType) unary_function<ArgType, typename Function::result_type>
|
||||
#define FUNCTOR_BINARY_BASE(ArgType) binary_function<ArgType, ArgType, typename Function::result_type>
|
||||
|
||||
#define MEM_VAR_UNARY_ARGS (argument_type p) const \
|
||||
{ return (m_pfn(p.*m_pv)); }
|
||||
#define MEM_VAR_BINARY_ARGS (argument_type p1, argument_type p2) const \
|
||||
{ return (m_pfn(p1.*m_pv, p2.*m_pv)); }
|
||||
|
||||
MEM_VAR_T(mem_var1, T&, VT T::*, FUNCTOR_UNARY_BASE(T&), MEM_VAR_UNARY_ARGS)
|
||||
MEM_VAR_T(const_mem_var1, const T&, const VT T::*, FUNCTOR_UNARY_BASE(T&), MEM_VAR_UNARY_ARGS)
|
||||
MEM_VAR_T(mem_var2, T&, VT T::*, FUNCTOR_BINARY_BASE(T&), MEM_VAR_BINARY_ARGS)
|
||||
MEM_VAR_T(const_mem_var2, const T&, const VT T::*, FUNCTOR_BINARY_BASE(T&), MEM_VAR_BINARY_ARGS)
|
||||
|
||||
#undef MEM_VAR_UNARY_ARGS
|
||||
#undef MEM_VAR_BINARY_ARGS
|
||||
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
/// Returned functor passes member variable \p mvp reference of given object to equal\<VT\>.
|
||||
/// \ingroup FunctorAccessors
|
||||
template <class T, typename VT>
|
||||
inline const_mem_var1_t<binder2nd<equal_to<VT> >, T, VT>
|
||||
mem_var_equal_to (const VT T::*mvp, const VT& v)
|
||||
{
|
||||
return (const_mem_var1_t<binder2nd<equal_to<VT> >,T,VT> (mvp, bind2nd(equal_to<VT>(), v)));
|
||||
}
|
||||
|
||||
/// Returned functor passes member variable \p mvp reference of given object to less\<VT\>.
|
||||
/// \ingroup FunctorAccessors
|
||||
template <class T, typename VT>
|
||||
inline const_mem_var1_t<binder2nd<less<VT> >, T, VT>
|
||||
mem_var_less (const VT T::*mvp, const VT& v)
|
||||
{
|
||||
return (const_mem_var1_t<binder2nd<less<VT> >,T,VT> (mvp, bind2nd(less<VT>(), v)));
|
||||
}
|
||||
|
||||
/// Returned functor passes member variable \p mvp reference of given object to equal\<VT\>.
|
||||
/// \ingroup FunctorAccessors
|
||||
template <class T, typename VT>
|
||||
inline const_mem_var2_t<equal_to<VT>, T, VT>
|
||||
mem_var_equal_to (const VT T::*mvp)
|
||||
{
|
||||
return (const_mem_var2_t<equal_to<VT>,T,VT> (mvp, equal_to<VT>()));
|
||||
}
|
||||
|
||||
/// Returned functor passes member variable \p mvp reference of given object to less\<VT\>.
|
||||
/// \ingroup FunctorAccessors
|
||||
template <class T, typename VT>
|
||||
inline const_mem_var2_t<less<VT>, T, VT>
|
||||
mem_var_less (const VT T::*mvp)
|
||||
{
|
||||
return (const_mem_var2_t<less<VT>,T,VT> (mvp, less<VT>()));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Dereference adaptors (uSTL extension)
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
#define DEREFERENCER_T(ClassName, ArgType, BaseClass, CallImpl, FunctorKey) \
|
||||
template <typename T, typename Function> \
|
||||
class ClassName : public BaseClass { \
|
||||
public: \
|
||||
typedef ArgType* argument_type; \
|
||||
typedef typename Function::result_type result_type; \
|
||||
public: \
|
||||
inline ClassName (Function pfn) : m_pfn (pfn) {} \
|
||||
inline result_type operator() CallImpl \
|
||||
private: \
|
||||
Function m_pfn; \
|
||||
}; \
|
||||
\
|
||||
template <typename T, typename Function> \
|
||||
inline ClassName<T,Function> _dereference (Function pfn, FunctorKey) \
|
||||
{ \
|
||||
return (ClassName<T,Function> (pfn)); \
|
||||
}
|
||||
|
||||
#define DEREF_UNARY_ARGS (argument_type p) const \
|
||||
{ return (m_pfn(*p)); }
|
||||
#define DEREF_BINARY_ARGS (argument_type p1, argument_type p2) const \
|
||||
{ return (m_pfn(*p1, *p2)); }
|
||||
|
||||
DEREFERENCER_T(deref1_t, T, FUNCTOR_UNARY_BASE(T*), DEREF_UNARY_ARGS, FUNCTOR_UNARY_BASE(T))
|
||||
DEREFERENCER_T(const_deref1_t, const T, FUNCTOR_UNARY_BASE(const T*), DEREF_UNARY_ARGS, FUNCTOR_UNARY_BASE(const T))
|
||||
DEREFERENCER_T(deref2_t, T, FUNCTOR_BINARY_BASE(T*), DEREF_BINARY_ARGS, FUNCTOR_BINARY_BASE(T))
|
||||
DEREFERENCER_T(const_deref2_t, const T, FUNCTOR_BINARY_BASE(const T*), DEREF_BINARY_ARGS, FUNCTOR_BINARY_BASE(const T))
|
||||
|
||||
#define dereference(f) _dereference(f,f)
|
||||
|
||||
#undef DEREF_UNARY_ARGS
|
||||
#undef DEREF_BINARY_ARGS
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// uheap.h
|
||||
//
|
||||
// Implementation of STL heap algorithms.
|
||||
//
|
||||
// The function prototypes are copied
|
||||
// exactly from the SGI version of STL documentation along with comments about
|
||||
// their use. The code is NOT the same, though the functionality is.
|
||||
//
|
||||
|
||||
#ifndef UHEAP_H_574B9EAF271A1C107190B4D575A356C5
|
||||
#define UHEAP_H_574B9EAF271A1C107190B4D575A356C5
|
||||
|
||||
#include "uvector.h"
|
||||
#include "ualgobase.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// \brief Returns true if the given range is a heap under \p comp.
|
||||
/// A heap is a sequentially encoded binary tree where for every node
|
||||
/// comp(node,child1) is false and comp(node,child2) is false.
|
||||
/// \ingroup HeapAlgorithms
|
||||
/// \ingroup ConditionAlgorithms
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
bool is_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
|
||||
{
|
||||
RandomAccessIterator iChild (first);
|
||||
for (; ++iChild < last; ++first)
|
||||
if (comp (*first, *iChild) || (++iChild < last && comp (*first, *iChild)))
|
||||
return (false);
|
||||
return (true);
|
||||
}
|
||||
|
||||
/// \brief make_heap turns the range [first, last) into a heap
|
||||
/// At completion, is_heap (first, last, comp) is true.
|
||||
/// The algorithm is adapted from "Classic Data Structures in C++" by Timothy Budd.
|
||||
/// \ingroup HeapAlgorithms
|
||||
/// \ingroup SortingAlgorithms
|
||||
///
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
void make_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
|
||||
{
|
||||
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
const value_type v (*first);
|
||||
uoff_t iChild, iHole = 0, iEnd (distance (first, last));
|
||||
while ((iChild = 2 * iHole + 1) < iEnd) {
|
||||
if (iChild + 1 < iEnd) // Pick the greater child
|
||||
iChild += comp (first[iChild], first[iChild + 1]);
|
||||
if (comp (first[iChild], v))
|
||||
break; // Done when parent is greater than both children.
|
||||
first[iHole] = first[iChild];
|
||||
iHole = iChild;
|
||||
}
|
||||
if (iHole < iEnd)
|
||||
first[iHole] = v;
|
||||
}
|
||||
|
||||
/// \brief Inserts the *--last into the preceeding range assumed to be a heap.
|
||||
/// \ingroup HeapAlgorithms
|
||||
/// \ingroup MutatingAlgorithms
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
void push_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
|
||||
{
|
||||
if (last <= first)
|
||||
return;
|
||||
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
|
||||
const value_type v (*--last);
|
||||
while (first < last) {
|
||||
RandomAccessIterator iParent = first + (distance(first, last) - 1) / 2;
|
||||
if (comp (v, *iParent))
|
||||
break;
|
||||
*last = *iParent;
|
||||
last = iParent;
|
||||
}
|
||||
*last = v;
|
||||
}
|
||||
|
||||
/// Removes the largest element from the heap (*first) and places it at *(last-1)
|
||||
/// [first, last-1) is a heap after this operation.
|
||||
/// \ingroup HeapAlgorithms
|
||||
/// \ingroup MutatingAlgorithms
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
void pop_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
|
||||
{
|
||||
if (--last <= first)
|
||||
return;
|
||||
iter_swap (first, last);
|
||||
make_heap (first, last, comp);
|
||||
}
|
||||
|
||||
/// Sorts heap [first, last) in descending order according to comp.
|
||||
/// \ingroup HeapAlgorithms
|
||||
/// \ingroup SortingAlgorithms
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
void sort_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
|
||||
{
|
||||
for (; first < last; --last)
|
||||
pop_heap (first, last, comp);
|
||||
}
|
||||
|
||||
#define HEAP_FN_WITH_LESS(rtype, name) \
|
||||
template <typename RandomAccessIterator>\
|
||||
inline rtype name (RandomAccessIterator first, RandomAccessIterator last) \
|
||||
{ \
|
||||
typedef typename iterator_traits<RandomAccessIterator>::value_type value_type; \
|
||||
return (name (first, last, less<value_type>())); \
|
||||
}
|
||||
HEAP_FN_WITH_LESS (bool, is_heap)
|
||||
HEAP_FN_WITH_LESS (void, make_heap)
|
||||
HEAP_FN_WITH_LESS (void, push_heap)
|
||||
HEAP_FN_WITH_LESS (void, pop_heap)
|
||||
HEAP_FN_WITH_LESS (void, sort_heap)
|
||||
#undef HEAP_FN_WITH_LESS
|
||||
|
||||
/// \class priority_queue uheap.h ustl.h
|
||||
/// \ingroup Sequences
|
||||
///
|
||||
/// \brief Sorted queue adapter to uSTL containers.
|
||||
///
|
||||
/// Acts just like the queue adapter, but keeps the elements sorted by priority
|
||||
/// specified by the given comparison operator.
|
||||
///
|
||||
template <typename T, typename Ctr = vector<T>, typename Comp = less<typename Ctr::value_type> >
|
||||
class priority_queue {
|
||||
public:
|
||||
typedef Ctr base_ctr;
|
||||
typedef typename base_ctr::value_type value_type;
|
||||
typedef typename base_ctr::size_type size_type;
|
||||
typedef typename base_ctr::const_pointer const_pointer;
|
||||
typedef typename base_ctr::const_reference reference;
|
||||
public:
|
||||
priority_queue (const Comp& c = Comp()) : m_v(), m_c (c) {}
|
||||
priority_queue (const_pointer f, const_pointer l, const Comp& c = Comp())
|
||||
: m_v (f, l), m_c (c) { make_heap (m_v.begin(), m_v.end(), m_c); }
|
||||
inline size_type size (void) const { return (m_v.size()); }
|
||||
inline bool empty (void) const { return (m_v.empty()); }
|
||||
inline reference top (void) const { return (m_v.at(0)); }
|
||||
inline void push (reference v) { m_v.push_back (v); make_heap (m_v.begin(), m_v.end(), m_c); }
|
||||
inline void pop (void) { pop_heap (m_v.begin(), m_v.end()); m_v.pop_back(); }
|
||||
private:
|
||||
base_ctr m_v; ///< Element container.
|
||||
Comp m_c; ///< Comparison functor by value.
|
||||
};
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// uios.h
|
||||
//
|
||||
// Types used by the streams for option setting.
|
||||
//
|
||||
|
||||
#ifndef UIOS_H_630C16E316F7650E3A02E1C6611B789A
|
||||
#define UIOS_H_630C16E316F7650E3A02E1C6611B789A
|
||||
|
||||
#include "utypes.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
class file_exception;
|
||||
|
||||
const char endl = '\n'; ///< End of line character.
|
||||
const char ends = '\0'; ///< End of string character.
|
||||
|
||||
/// Defines types and constants used by all stream classes.
|
||||
class ios_base {
|
||||
public:
|
||||
/// Used to set parameters for stringstreams
|
||||
enum fmtflags {
|
||||
boolalpha = (1 << 0), ///< Boolean values printed as text.
|
||||
dec = (1 << 1), ///< Decimal number output.
|
||||
fixed = (1 << 2), ///< Fixed-point float output.
|
||||
hex = (1 << 3), ///< Hexadecimal number output.
|
||||
internal = (1 << 4),
|
||||
left = (1 << 5), ///< Left alignment.
|
||||
oct = (1 << 6), ///< Octal number output.
|
||||
right = (1 << 7), ///< Right alignment.
|
||||
scientific = (1 << 8), ///< Scientific float format.
|
||||
showbase = (1 << 9), ///< Add 0x or 0 prefixes on hex and octal numbers.
|
||||
showpoint = (1 << 10), ///< Print decimal point.
|
||||
showpos = (1 << 11),
|
||||
skipws = (1 << 12), ///< Skip whitespace when reading.
|
||||
unitbuf = (1 << 13),
|
||||
uppercase = (1 << 14),
|
||||
adjustfield = (1 << 15),
|
||||
basefield = (1 << 16),
|
||||
floatfield = (1 << 17)
|
||||
};
|
||||
/// For file-based streams, specifies fd mode.
|
||||
enum openmode_bits {
|
||||
in = (1 << 0),
|
||||
out = (1 << 1),
|
||||
app = (1 << 2),
|
||||
ate = (1 << 3),
|
||||
binary = (1 << 4),
|
||||
trunc = (1 << 5),
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
nonblock= (1 << 6),
|
||||
nocreate= (1 << 7),
|
||||
noctty = (1 << 8),
|
||||
nombits = 9
|
||||
#endif
|
||||
};
|
||||
/// Seek directions, equivalent to SEEK_SET, SEEK_CUR, and SEEK_END.
|
||||
enum seekdir {
|
||||
beg,
|
||||
cur,
|
||||
end
|
||||
};
|
||||
/// I/O state bitmasks.
|
||||
enum iostate_bits {
|
||||
goodbit = 0,
|
||||
badbit = (1 << 0),
|
||||
eofbit = (1 << 1),
|
||||
failbit = (1 << 2),
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
nbadbits = 3,
|
||||
allbadbits = 0x7
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef uint32_t openmode; ///< Holds openmode_bits.
|
||||
typedef uint32_t iostate; ///< Holds iostate_bits for a file stream.
|
||||
typedef file_exception failure; ///< Thrown by fstream on errors.
|
||||
|
||||
static const char c_DefaultDelimiters [16]; ///< Default word delimiters for stringstreams.
|
||||
public:
|
||||
inline ios_base (void) : m_State (goodbit), m_Exceptions (goodbit) {}
|
||||
inline iostate rdstate (void) const { return (m_State); }
|
||||
inline bool bad (void) const { return (rdstate() & badbit); }
|
||||
inline bool good (void) const { return (rdstate() == goodbit); }
|
||||
inline bool fail (void) const { return (rdstate() & (badbit | failbit)); }
|
||||
inline bool eof (void) const { return (rdstate() & eofbit); }
|
||||
inline bool operator! (void) const { return (fail()); }
|
||||
inline void clear (iostate v = goodbit) { m_State = v; }
|
||||
inline void setstate (iostate v) { m_State |= v; }
|
||||
inline iostate exceptions (void) const { return (m_Exceptions); }
|
||||
inline iostate exceptions (iostate v) { return (m_Exceptions = v); }
|
||||
protected:
|
||||
inline bool set_and_throw (iostate v) { setstate(v); return (exceptions() & v); }
|
||||
private:
|
||||
uint16_t m_State; ///< Open state, using ios::iostate_bits.
|
||||
uint16_t m_Exceptions; ///< Exception flags, using ios::iostate_bits.
|
||||
};
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// uiosfunc.h
|
||||
//
|
||||
|
||||
#ifndef UIOSFUNC_H_730C16E316F7650E3A02E1C6611B789A
|
||||
#define UIOSFUNC_H_730C16E316F7650E3A02E1C6611B789A
|
||||
|
||||
#include "sostream.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
class ios : public ios_base {
|
||||
public:
|
||||
/// \class align uiosfunc.h ustl.h
|
||||
/// \ingroup StreamFunctors
|
||||
/// \brief Stream functor to allow inline align() calls.
|
||||
///
|
||||
/// Example: os << ios::align(sizeof(uint16_t));
|
||||
///
|
||||
class align {
|
||||
public:
|
||||
inline explicit align (size_t grain = c_DefaultAlignment) : m_Grain(grain) {}
|
||||
inline istream& apply (istream& is) const { is.align (m_Grain); return (is); }
|
||||
inline ostream& apply (ostream& os) const { os.align (m_Grain); return (os); }
|
||||
inline size_t stream_size (void) const { return (m_Grain - 1); }
|
||||
private:
|
||||
const size_t m_Grain;
|
||||
};
|
||||
|
||||
/// \class talign uiosfunc.h ustl.h
|
||||
/// \ingroup StreamFunctors
|
||||
/// \brief Stream functor to allow type-based alignment.
|
||||
template <typename T>
|
||||
class talign : public align {
|
||||
public:
|
||||
inline explicit talign (void) : align (alignof (T())) {}
|
||||
};
|
||||
|
||||
/// \class skip uiosfunc.h ustl.h
|
||||
/// \ingroup StreamFunctors
|
||||
/// \brief Stream functor to allow inline skip() calls.
|
||||
///
|
||||
/// Example: os << ios::skip(sizeof(uint16_t));
|
||||
///
|
||||
class skip {
|
||||
public:
|
||||
inline explicit skip (size_t nBytes) : m_nBytes(nBytes) {}
|
||||
inline istream& apply (istream& is) const { is.skip (m_nBytes); return (is); }
|
||||
inline ostream& apply (ostream& os) const { os.skip (m_nBytes); return (os); }
|
||||
inline size_t stream_size (void) const { return (m_nBytes); }
|
||||
private:
|
||||
const size_t m_nBytes;
|
||||
};
|
||||
|
||||
/// \class width uiosfunc.h ustl.h
|
||||
/// \ingroup StreamFunctors
|
||||
/// \brief Stream functor to allow inline set_width() calls.
|
||||
///
|
||||
/// Example: os << ios::width(15);
|
||||
///
|
||||
class width {
|
||||
public:
|
||||
inline explicit width (size_t nBytes) : m_nBytes(nBytes) {}
|
||||
inline ostringstream& apply (ostringstream& os) const { os.set_width (m_nBytes); return (os); }
|
||||
private:
|
||||
const size_t m_nBytes;
|
||||
};
|
||||
|
||||
/// \class base uiosfunc.h ustl.h
|
||||
/// \ingroup StreamFunctors
|
||||
/// \brief Stream functor to allow inline set_base() calls.
|
||||
///
|
||||
/// Example: os << ios::base(15);
|
||||
///
|
||||
class base {
|
||||
public:
|
||||
inline explicit base (size_t n) : m_Base(n) {}
|
||||
inline ostringstream& apply (ostringstream& os) const { os.set_base (m_Base); return (os); }
|
||||
private:
|
||||
const size_t m_Base;
|
||||
};
|
||||
};
|
||||
|
||||
inline istream& operator>> (istream& is, const ios::skip& op) { return (op.apply (is)); }
|
||||
inline ostream& operator<< (ostream& os, const ios::skip& op) { return (op.apply (os)); }
|
||||
inline size_t stream_size_of (const ios::skip& op) { return (op.stream_size()); }
|
||||
inline istream& operator>> (istream& is, const ios::align& op) { return (op.apply (is)); }
|
||||
inline ostream& operator<< (ostream& os, const ios::align& op) { return (op.apply (os)); }
|
||||
inline size_t stream_size_of (const ios::align& op) { return (op.stream_size()); }
|
||||
inline ostringstream& operator<< (ostringstream& os, const ios::width& op) { return (op.apply (os)); }
|
||||
inline ostringstream& operator<< (ostringstream& os, const ios::base& op) { return (op.apply (os)); }
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
CAST_STREAMABLE(ustl::ios::fmtflags, uint32_t)
|
||||
CAST_STREAMABLE(ustl::ios::seekdir, uint32_t)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,268 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
/// \file uiterator.h
|
||||
/// \brief Contains various iterator adapters.
|
||||
//
|
||||
|
||||
#ifndef UITERATOR_H_5BCA176C7214A30F2069E2614D2DC226
|
||||
#define UITERATOR_H_5BCA176C7214A30F2069E2614D2DC226
|
||||
|
||||
#include "uassert.h"
|
||||
#include "utypes.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// \struct iterator_traits uiterator.h ustl.h
|
||||
/// \brief Contains the type traits of \p Iterator
|
||||
///
|
||||
template <typename Iterator>
|
||||
struct iterator_traits {
|
||||
typedef typename Iterator::value_type value_type;
|
||||
typedef typename Iterator::difference_type difference_type;
|
||||
typedef typename Iterator::pointer pointer;
|
||||
typedef typename Iterator::reference reference;
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
template <typename T>
|
||||
struct iterator_traits<T*> {
|
||||
typedef T value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef const T* const_pointer;
|
||||
typedef T* pointer;
|
||||
typedef T& reference;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct iterator_traits<const T*> {
|
||||
typedef T value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef const T* const_pointer;
|
||||
typedef const T* pointer;
|
||||
typedef const T& reference;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct iterator_traits<void*> {
|
||||
typedef uint8_t value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef const void* const_pointer;
|
||||
typedef void* pointer;
|
||||
typedef value_type& reference;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct iterator_traits<const void*> {
|
||||
typedef uint8_t value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef const void* const_pointer;
|
||||
typedef const void* pointer;
|
||||
typedef const value_type& reference;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// \class reverse_iterator uiterator.h ustl.h
|
||||
/// \ingroup IteratorAdaptors
|
||||
/// \brief Wraps \p Iterator to behave in an exactly opposite manner.
|
||||
///
|
||||
template <class Iterator>
|
||||
class reverse_iterator {
|
||||
public:
|
||||
typedef typename iterator_traits<Iterator>::value_type value_type;
|
||||
typedef typename iterator_traits<Iterator>::difference_type difference_type;
|
||||
typedef typename iterator_traits<Iterator>::pointer pointer;
|
||||
typedef typename iterator_traits<Iterator>::reference reference;
|
||||
public:
|
||||
reverse_iterator (void) : m_i() {}
|
||||
explicit reverse_iterator (Iterator iter) : m_i (iter) {}
|
||||
inline bool operator== (const reverse_iterator& iter) const { return (m_i == iter.m_i); }
|
||||
inline bool operator< (const reverse_iterator& iter) const { return (iter.m_i < m_i); }
|
||||
inline Iterator base (void) const { return (m_i); }
|
||||
inline reference operator* (void) const { Iterator prev (m_i); --prev; return (*prev); }
|
||||
inline pointer operator-> (void) const { return (&(operator*())); }
|
||||
inline reverse_iterator& operator++ (void) { -- m_i; return (*this); }
|
||||
inline reverse_iterator& operator-- (void) { ++ m_i; return (*this); }
|
||||
inline reverse_iterator operator++ (int) { reverse_iterator prev (*this); -- m_i; return (prev); }
|
||||
inline reverse_iterator operator-- (int) { reverse_iterator prev (*this); ++ m_i; return (prev); }
|
||||
inline reverse_iterator& operator+= (size_t n) { m_i -= n; return (*this); }
|
||||
inline reverse_iterator& operator-= (size_t n) { m_i += n; return (*this); }
|
||||
inline reverse_iterator operator+ (size_t n) const { return (reverse_iterator (m_i - n)); }
|
||||
inline reverse_iterator operator- (size_t n) const { return (reverse_iterator (m_i + n)); }
|
||||
inline reference operator[] (uoff_t n) const { return (*(*this + n)); }
|
||||
inline difference_type operator- (const reverse_iterator& i) const { return (distance (m_i, i.m_i)); }
|
||||
protected:
|
||||
Iterator m_i;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// \class insert_iterator uiterator.h ustl.h
|
||||
/// \ingroup IteratorAdaptors
|
||||
/// \brief Calls insert on bound container for each assignment.
|
||||
///
|
||||
template <class Container>
|
||||
class insert_iterator {
|
||||
public:
|
||||
typedef typename Container::value_type value_type;
|
||||
typedef typename Container::difference_type difference_type;
|
||||
typedef typename Container::pointer pointer;
|
||||
typedef typename Container::reference reference;
|
||||
typedef typename Container::iterator iterator;
|
||||
public:
|
||||
explicit insert_iterator (Container& ctr, iterator ip) : m_rCtr (ctr), m_ip (ip) {}
|
||||
inline insert_iterator& operator= (typename Container::const_reference v)
|
||||
{ m_ip = m_rCtr.insert (m_ip, v); return (*this); }
|
||||
inline insert_iterator& operator* (void) { return (*this); }
|
||||
inline insert_iterator& operator++ (void) { ++ m_ip; return (*this); }
|
||||
inline insert_iterator operator++ (int) { insert_iterator prev (*this); ++ m_ip; return (*this); }
|
||||
protected:
|
||||
Container& m_rCtr;
|
||||
iterator m_ip;
|
||||
};
|
||||
|
||||
/// Returns the insert_iterator for \p ctr.
|
||||
template <class Container>
|
||||
inline insert_iterator<Container> inserter (Container& ctr, typename Container::iterator ip)
|
||||
{
|
||||
return (insert_iterator<Container> (ctr, ip));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// \class back_insert_iterator uiterator.h ustl.h
|
||||
/// \ingroup IteratorAdaptors
|
||||
/// \brief Calls push_back on bound container for each assignment.
|
||||
///
|
||||
template <class Container>
|
||||
class back_insert_iterator {
|
||||
public:
|
||||
typedef typename Container::value_type value_type;
|
||||
typedef typename Container::difference_type difference_type;
|
||||
typedef typename Container::pointer pointer;
|
||||
typedef typename Container::reference reference;
|
||||
public:
|
||||
explicit back_insert_iterator (Container& ctr) : m_rCtr (ctr) {}
|
||||
inline back_insert_iterator& operator= (typename Container::const_reference v)
|
||||
{ m_rCtr.push_back (v); return (*this); }
|
||||
inline back_insert_iterator& operator* (void) { return (*this); }
|
||||
inline back_insert_iterator& operator++ (void) { return (*this); }
|
||||
inline back_insert_iterator operator++ (int) { return (*this); }
|
||||
protected:
|
||||
Container& m_rCtr;
|
||||
};
|
||||
|
||||
/// Returns the back_insert_iterator for \p ctr.
|
||||
template <class Container>
|
||||
inline back_insert_iterator<Container> back_inserter (Container& ctr)
|
||||
{
|
||||
return (back_insert_iterator<Container> (ctr));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// \class index_iterate uiterator.h ustl.h
|
||||
/// \ingroup IteratorAdaptors
|
||||
///
|
||||
/// \brief Allows iteration through an index container.
|
||||
///
|
||||
/// Converts an iterator into a container of uoff_t indexes to an
|
||||
/// iterator of iterators into another container.
|
||||
///
|
||||
template <typename RandomAccessIterator, typename IndexIterator>
|
||||
class index_iterate {
|
||||
public:
|
||||
typedef RandomAccessIterator value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef RandomAccessIterator* pointer;
|
||||
typedef RandomAccessIterator reference;
|
||||
public:
|
||||
index_iterate (void) : m_Base(), m_i() {}
|
||||
index_iterate (RandomAccessIterator ibase, IndexIterator iindex) : m_Base (ibase), m_i (iindex) {}
|
||||
inline bool operator== (const index_iterate& i) const { return (m_i == i.m_i); }
|
||||
inline bool operator< (const index_iterate& i) const { return (m_i < i.m_i); }
|
||||
inline bool operator== (const RandomAccessIterator& i) const { return (m_Base == i); }
|
||||
inline bool operator< (const RandomAccessIterator& i) const { return (m_Base < i); }
|
||||
inline IndexIterator base (void) const { return (m_i); }
|
||||
inline reference operator* (void) const { return (advance(m_Base, *m_i)); }
|
||||
inline pointer operator-> (void) const { return (&(operator*())); }
|
||||
inline index_iterate& operator++ (void) { ++ m_i; return (*this); }
|
||||
inline index_iterate& operator-- (void) { -- m_i; return (*this); }
|
||||
inline index_iterate operator++ (int) { index_iterate prev (*this); ++ m_i; return (prev); }
|
||||
inline index_iterate operator-- (int) { index_iterate prev (*this); -- m_i; return (prev); }
|
||||
inline index_iterate& operator+= (size_t n) { m_i += n; return (*this); }
|
||||
inline index_iterate& operator-= (size_t n) { m_i -= n; return (*this); }
|
||||
inline index_iterate operator+ (size_t n) const { return (index_iterate (m_Base, m_i + n)); }
|
||||
inline index_iterate operator- (size_t n) const { return (index_iterate (m_Base, m_i - n)); }
|
||||
inline reference operator[] (uoff_t n) const { return (*(*this + n)); }
|
||||
inline difference_type operator- (const index_iterate& i) const { return (distance (m_i, i.m_i)); }
|
||||
private:
|
||||
RandomAccessIterator m_Base;
|
||||
IndexIterator m_i;
|
||||
};
|
||||
|
||||
/// Returns an index_iterate for \p ibase over \p iindex.
|
||||
template <typename RandomAccessIterator, typename IndexIterator>
|
||||
inline index_iterate<RandomAccessIterator, IndexIterator> index_iterator (RandomAccessIterator ibase, IndexIterator iindex)
|
||||
{
|
||||
return (index_iterate<RandomAccessIterator, IndexIterator> (ibase, iindex));
|
||||
}
|
||||
|
||||
/// Converts the indexes in \p xc to iterators in \p ic of base \p ibase.
|
||||
template <typename IndexContainer, typename IteratorContainer>
|
||||
inline void indexv_to_iteratorv (typename IteratorContainer::value_type ibase, const IndexContainer& xc, IteratorContainer& ic)
|
||||
{
|
||||
ic.resize (xc.size());
|
||||
copy_n (index_iterator (ibase, xc.begin()), xc.size(), ic.begin());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/// Converts the given const_iterator into an iterator.
|
||||
///
|
||||
template <typename Container>
|
||||
inline typename Container::iterator unconst (typename Container::const_iterator i, Container& ctr)
|
||||
{
|
||||
const Container& cctr = ctr;
|
||||
return (ctr.begin() + (i - cctr.begin()));
|
||||
}
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
#define IBYI(Iter1, Iter2, Ctr1, Ctr2) \
|
||||
template <typename Container1, typename Container2> \
|
||||
inline typename Container2::Iter2 ibyi (typename Container1::Iter1 idx, Ctr1& ctr1, Ctr2& ctr2) \
|
||||
{ \
|
||||
assert (ctr1.size() == ctr2.size()); \
|
||||
return (ctr2.begin() + (idx - ctr1.begin())); \
|
||||
}
|
||||
|
||||
IBYI(const_iterator, const_iterator, const Container1, const Container2)
|
||||
IBYI(iterator, iterator, Container1, Container2)
|
||||
IBYI(const_iterator, iterator, const Container1, Container2)
|
||||
IBYI(iterator, const_iterator, Container1, const Container2)
|
||||
|
||||
#else // DOXYGEN
|
||||
|
||||
#error This declaration is for doxygen only; it is not compiled.
|
||||
|
||||
/// Converts a const_iterator in one container into a const_iterator in another container.
|
||||
template <typename Container1, typename Container2>
|
||||
inline typename Container2::iterator ibyi (typename Container1::iterator idx, Container1& ctr1, Container2& ctr2) {}
|
||||
|
||||
#endif // DOXYGEN
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,223 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// ulaalgo.h
|
||||
//
|
||||
|
||||
#ifndef ULAALGO_H_2E403D182E83FB596AFB800E68B255A1
|
||||
#define ULAALGO_H_2E403D182E83FB596AFB800E68B255A1
|
||||
|
||||
#include "umatrix.h"
|
||||
#include "simd.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// \brief Creates an identity matrix in \p m
|
||||
/// \ingroup NumericAlgorithms
|
||||
template <size_t NX, size_t NY, typename T>
|
||||
void load_identity (matrix<NX,NY,T>& m)
|
||||
{
|
||||
fill_n (m.begin(), NX * NY, 0);
|
||||
for (typename matrix<NX,NY,T>::iterator i = m.begin(); i < m.end(); i += NX + 1)
|
||||
*i = 1;
|
||||
}
|
||||
|
||||
/// \brief Multiplies two matrices
|
||||
/// \ingroup NumericAlgorithms
|
||||
template <size_t NX, size_t NY, typename T>
|
||||
matrix<NY,NY,T> operator* (const matrix<NX,NY,T>& m1, const matrix<NY,NX,T>& m2)
|
||||
{
|
||||
matrix<NY,NY,T> mr;
|
||||
for (uoff_t ry = 0; ry < NY; ++ ry) {
|
||||
for (uoff_t rx = 0; rx < NY; ++ rx) {
|
||||
T dpv (0);
|
||||
for (uoff_t x = 0; x < NX; ++ x)
|
||||
dpv += m1[ry][x] * m2[x][rx];
|
||||
mr[ry][rx] = dpv;
|
||||
}
|
||||
}
|
||||
return (mr);
|
||||
}
|
||||
|
||||
/// \brief Transforms vector \p t with matrix \p m
|
||||
/// \ingroup NumericAlgorithms
|
||||
template <size_t NX, size_t NY, typename T>
|
||||
tuple<NX,T> operator* (const tuple<NY,T>& t, const matrix<NX,NY,T>& m)
|
||||
{
|
||||
tuple<NX,T> tr;
|
||||
for (uoff_t x = 0; x < NX; ++ x) {
|
||||
T dpv (0);
|
||||
for (uoff_t y = 0; y < NY; ++ y)
|
||||
dpv += t[y] * m[y][x];
|
||||
tr[x] = dpv;
|
||||
}
|
||||
return (tr);
|
||||
}
|
||||
|
||||
/// \brief Transposes (exchanges rows and columns) matrix \p m.
|
||||
/// \ingroup NumericAlgorithms
|
||||
template <size_t N, typename T>
|
||||
void transpose (matrix<N,N,T>& m)
|
||||
{
|
||||
for (uoff_t x = 0; x < N; ++ x)
|
||||
for (uoff_t y = x; y < N; ++ y)
|
||||
swap (m[x][y], m[y][x]);
|
||||
}
|
||||
|
||||
#if WANT_UNROLLED_COPY
|
||||
|
||||
#if CPU_HAS_SSE
|
||||
|
||||
#if linux // Non-linux gcc versions (BSD, Solaris) can't handle "x" constraint and provide no alternative.
|
||||
template <>
|
||||
inline void load_identity (matrix<4,4,float>& m)
|
||||
{
|
||||
asm (
|
||||
"movaps %4, %%xmm1 \n\t" // 1 0 0 0
|
||||
"movups %4, %0 \n\t" // 1 0 0 0
|
||||
"shufps $0xB1,%%xmm1,%%xmm1 \n\t" // 0 1 0 0
|
||||
"movups %%xmm1, %1 \n\t" // 0 1 0 0
|
||||
"shufps $0x4F,%4,%%xmm1 \n\t" // 0 0 1 0
|
||||
"shufps $0x1B,%4,%4 \n\t" // 0 0 0 1
|
||||
"movups %%xmm1, %2 \n\t" // 0 0 1 0
|
||||
"movups %4, %3" // 0 0 0 1
|
||||
: "=m"(m[0][0]), "=m"(m[1][0]), "=m"(m[2][0]), "=m"(m[3][0])
|
||||
: "x"(1.0f)
|
||||
: "xmm1"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void _sse_load_matrix (const float* m)
|
||||
{
|
||||
asm (
|
||||
"movups %0, %%xmm4 \n\t" // xmm4 = m[1 2 3 4]
|
||||
"movups %1, %%xmm5 \n\t" // xmm5 = m[1 2 3 4]
|
||||
"movups %2, %%xmm6 \n\t" // xmm6 = m[1 2 3 4]
|
||||
"movups %3, %%xmm7" // xmm7 = m[1 2 3 4]
|
||||
: : "m"(m[0]), "m"(m[4]), "m"(m[8]), "m"(m[12])
|
||||
: "xmm4", "xmm5", "xmm6", "xmm7"
|
||||
);
|
||||
}
|
||||
|
||||
inline void _sse_transform_to_vector (float* result)
|
||||
{
|
||||
asm (
|
||||
"movaps %%xmm0, %%xmm1 \n\t" // xmm1 = t[0 1 2 3]
|
||||
"movaps %%xmm0, %%xmm2 \n\t" // xmm1 = t[0 1 2 3]
|
||||
"movaps %%xmm0, %%xmm3 \n\t" // xmm1 = t[0 1 2 3]
|
||||
"shufps $0x00, %%xmm0, %%xmm0 \n\t" // xmm0 = t[0 0 0 0]
|
||||
"shufps $0x66, %%xmm1, %%xmm1 \n\t" // xmm1 = t[1 1 1 1]
|
||||
"shufps $0xAA, %%xmm2, %%xmm2 \n\t" // xmm2 = t[2 2 2 2]
|
||||
"shufps $0xFF, %%xmm3, %%xmm3 \n\t" // xmm3 = t[3 3 3 3]
|
||||
"mulps %%xmm4, %%xmm0 \n\t" // xmm0 = t[0 0 0 0] * m[0 1 2 3]
|
||||
"mulps %%xmm5, %%xmm1 \n\t" // xmm1 = t[1 1 1 1] * m[0 1 2 3]
|
||||
"addps %%xmm1, %%xmm0 \n\t" // xmm0 = xmm0 + xmm1
|
||||
"mulps %%xmm6, %%xmm2 \n\t" // xmm2 = t[2 2 2 2] * m[0 1 2 3]
|
||||
"mulps %%xmm7, %%xmm3 \n\t" // xmm3 = t[3 3 3 3] * m[0 1 2 3]
|
||||
"addps %%xmm3, %%xmm2 \n\t" // xmm2 = xmm2 + xmm3
|
||||
"addps %%xmm2, %%xmm0 \n\t" // xmm0 = result
|
||||
"movups %%xmm0, %0"
|
||||
: "=m"(result[0]) :
|
||||
: "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
|
||||
);
|
||||
}
|
||||
|
||||
template <>
|
||||
tuple<4,float> operator* (const tuple<4,float>& t, const matrix<4,4,float>& m)
|
||||
{
|
||||
tuple<4,float> result;
|
||||
_sse_load_matrix (m.begin());
|
||||
asm ("movups %0, %%xmm0" : : "m"(t[0]) : "xmm0");
|
||||
_sse_transform_to_vector (result.begin());
|
||||
return (result);
|
||||
}
|
||||
|
||||
template <>
|
||||
matrix<4,4,float> operator* (const matrix<4,4,float>& m1, const matrix<4,4,float>& m2)
|
||||
{
|
||||
matrix<4,4,float> result;
|
||||
_sse_load_matrix (m2.begin());
|
||||
for (uoff_t r = 0; r < 4; ++ r) {
|
||||
asm ("movups %0, %%xmm0" : : "m"(m1[r][0]) : "xmm0");
|
||||
_sse_transform_to_vector (result[r]);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
#elif CPU_HAS_3DNOW
|
||||
|
||||
/// Specialization for 4-component vector transform, the slow part of 3D graphics.
|
||||
template <>
|
||||
tuple<4,float> operator* (const tuple<4,float>& t, const matrix<4,4,float>& m)
|
||||
{
|
||||
tuple<4,float> result;
|
||||
// This is taken from "AMD Athlon Code Optimization Guide" from AMD. 18 cycles!
|
||||
// If you are writing a 3D engine, you may want to copy it instead of calling it
|
||||
// because of the femms instruction at the end, which takes 2 cycles.
|
||||
asm (
|
||||
"movq %2, %%mm0 \n\t" // y | x
|
||||
"movq %3, %%mm1 \n\t" // w | z
|
||||
"movq %%mm0, %%mm2 \n\t" // y | x
|
||||
"movq %4, %%mm3 \n\t" // m[0][1] | m[0][0]
|
||||
"punpckldq %%mm0, %%mm0 \n\t" // x | x
|
||||
"movq %6, %%mm4 \n\t" // m[1][1] | m[1][0]
|
||||
"pfmul %%mm0, %%mm3 \n\t" // x*m[0][1] | x*m[0][0]
|
||||
"punpckhdq %%mm2, %%mm2 \n\t" // y | y
|
||||
"pfmul %%mm2, %%mm4 \n\t" // y*m[1][1] | y*m[1][0]
|
||||
"movq %5, %%mm5 \n\t" // m[0][3] | m[0][2]
|
||||
"movq %7, %%mm7 \n\t" // m[1][3] | m[1][2]
|
||||
"movq %%mm1, %%mm6 \n\t" // w | z
|
||||
"pfmul %%mm0, %%mm5 \n\t" // x*m[0][3] | v0>x*m[0][2]
|
||||
"movq %8, %%mm0 \n\t" // m[2][1] | m[2][0]
|
||||
"punpckldq %%mm1, %%mm1 \n\t" // z | z
|
||||
"pfmul %%mm2, %%mm7 \n\t" // y*m[1][3] | y*m[1][2]
|
||||
"movq %9, %%mm2 \n\t" // m[2][3] | m[2][2]
|
||||
"pfmul %%mm1, %%mm0 \n\t" // z*m[2][1] | z*m[2][0]
|
||||
"pfadd %%mm4, %%mm3 \n\t" // x*m[0][1]+y*m[1][1] | x*m[0][0]+y*m[1][0]
|
||||
"movq %10, %%mm4 \n\t" // m[3][1] | m[3][0]
|
||||
"pfmul %%mm1, %%mm2 \n\t" // z*m[2][3] | z*m[2][2]
|
||||
"pfadd %%mm7, %%mm5 \n\t" // x*m[0][3]+y*m[1][3] | x*m[0][2]+y*m[1][2]
|
||||
"movq %11, %%mm1 \n\t" // m[3][3] | m[3][2]
|
||||
"punpckhdq %%mm6, %%mm6 \n\t" // w | w
|
||||
"pfadd %%mm0, %%mm3 \n\t" // x*m[0][1]+y*m[1][1]+z*m[2][1] | x*m[0][0]+y*m[1][0]+z*m[2][0]
|
||||
"pfmul %%mm6, %%mm4 \n\t" // w*m[3][1] | w*m[3][0]
|
||||
"pfmul %%mm6, %%mm1 \n\t" // w*m[3][3] | w*m[3][2]
|
||||
"pfadd %%mm2, %%mm5 \n\t" // x*m[0][3]+y*m[1][3]+z*m[2][3] | x*m[0][2]+y*m[1][2]+z*m[2][2]
|
||||
"pfadd %%mm4, %%mm3 \n\t" // x*m[0][1]+y*m[1][1]+z*m[2][1]+w*m[3][1] | x*m[0][0]+y*m[1][0]+z*m[2][0]+w*m[3][0]
|
||||
"movq %%mm3, %0 \n\t" // store result->y | result->x
|
||||
"pfadd %%mm1, %%mm5 \n\t" // x*m[0][3]+y*m[1][3]+z*m[2][3]+w*m[3][3] | x*m[0][2]+y*m[1][2]+z*m[2][2]+w*m[3][2]
|
||||
"movq %%mm5, %1" // store result->w | result->z
|
||||
: "=m"(result[0]), "=m"(result[2])
|
||||
: "m"(t[0]), "m"(t[2]),
|
||||
"m"(m[0][0]), "m"(m[0][2]),
|
||||
"m"(m[1][0]), "m"(m[1][2]),
|
||||
"m"(m[2][0]), "m"(m[2][2]),
|
||||
"m"(m[3][0]), "m"(m[3][2])
|
||||
: "mm0","mm1","mm2","mm3","mm4","mm5","mm6","mm7"
|
||||
);
|
||||
simd::reset_mmx();
|
||||
return (result);
|
||||
}
|
||||
|
||||
#else // If no processor extensions, just unroll the multiplication
|
||||
|
||||
/// Specialization for 4-component vector transform, the slow part of 3D graphics.
|
||||
template <>
|
||||
tuple<4,float> operator* (const tuple<4,float>& t, const matrix<4,4,float>& m)
|
||||
{
|
||||
tuple<4,float> tr;
|
||||
for (uoff_t i = 0; i < 4; ++ i)
|
||||
tr[i] = t[0] * m[0][i] + t[1] * m[1][i] + t[2] * m[2][i] + t[3] * m[3][i];
|
||||
return (tr);
|
||||
}
|
||||
|
||||
#endif // CPU_HAS_3DNOW
|
||||
#endif // WANT_UNROLLED_COPY
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// ulimits.h
|
||||
//
|
||||
|
||||
#ifndef ULIMITS_H_1C2192EA3821E0811BBAF86B0F048364
|
||||
#define ULIMITS_H_1C2192EA3821E0811BBAF86B0F048364
|
||||
|
||||
#include "utypes.h"
|
||||
#include <stdint.h>
|
||||
|
||||
namespace ustl {
|
||||
|
||||
// Android
|
||||
#ifndef UINTPTR_MAX
|
||||
#define UINTPTR_MAX UINT32_MAX
|
||||
#endif
|
||||
|
||||
#ifndef UINT32_MAX
|
||||
#define UINT32_MAX (0xffffffff)
|
||||
#endif
|
||||
|
||||
/// \class numeric_limits ulimits.h ustl.h
|
||||
/// \brief Defines numeric limits for a type.
|
||||
///
|
||||
template <typename T>
|
||||
struct numeric_limits {
|
||||
/// Returns the minimum value for type T.
|
||||
static inline T min (void) { return (T(0)); }
|
||||
/// Returns the minimum value for type T.
|
||||
static inline T max (void) { return (T(0)); }
|
||||
static const bool is_signed = false; ///< True if the type is signed.
|
||||
static const bool is_integer = false; ///< True if stores an exact value.
|
||||
static const bool is_integral = false; ///< True if fixed size and cast-copyable.
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
template <typename T>
|
||||
struct numeric_limits<T*> {
|
||||
static inline T* min (void) { return (NULL); }
|
||||
static inline T* max (void) { return (UINTPTR_MAX); }
|
||||
static const bool is_signed = false;
|
||||
static const bool is_integer = true;
|
||||
static const bool is_integral = true;
|
||||
};
|
||||
|
||||
#define _NUMERIC_LIMITS(type, minVal, maxVal, bSigned, bInteger, bIntegral) \
|
||||
template <> \
|
||||
struct numeric_limits<type> { \
|
||||
static inline type min (void) { return (minVal); } \
|
||||
static inline type max (void) { return (maxVal); } \
|
||||
static const bool is_signed = bSigned; \
|
||||
static const bool is_integer = bInteger; \
|
||||
static const bool is_integral = bIntegral; \
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// type min max signed integer integral
|
||||
//--------------------------------------------------------------------------------------
|
||||
_NUMERIC_LIMITS (bool, false, true, false, true, true);
|
||||
_NUMERIC_LIMITS (char, SCHAR_MIN, SCHAR_MAX, true, true, true);
|
||||
_NUMERIC_LIMITS (int, INT_MIN, INT_MAX, true, true, true);
|
||||
_NUMERIC_LIMITS (short, SHRT_MIN, SHRT_MAX, true, true, true);
|
||||
_NUMERIC_LIMITS (long, LONG_MIN, LONG_MAX, true, true, true);
|
||||
#if HAVE_THREE_CHAR_TYPES
|
||||
_NUMERIC_LIMITS (signed char, SCHAR_MIN, SCHAR_MAX, true, true, true);
|
||||
#endif
|
||||
_NUMERIC_LIMITS (unsigned char, 0, UCHAR_MAX, false, true, true);
|
||||
_NUMERIC_LIMITS (unsigned int, 0, UINT_MAX, false, true, true);
|
||||
_NUMERIC_LIMITS (unsigned short,0, USHRT_MAX, false, true, true);
|
||||
_NUMERIC_LIMITS (unsigned long, 0, ULONG_MAX, false, true, true);
|
||||
_NUMERIC_LIMITS (wchar_t, 0, WCHAR_MAX, false, true, true);
|
||||
_NUMERIC_LIMITS (float, FLT_MIN, FLT_MAX, true, false, true);
|
||||
_NUMERIC_LIMITS (double, DBL_MIN, DBL_MAX, true, false, true);
|
||||
_NUMERIC_LIMITS (long double, LDBL_MIN, LDBL_MAX, true, false, true);
|
||||
#ifdef HAVE_LONG_LONG
|
||||
_NUMERIC_LIMITS (long long, LLONG_MIN, LLONG_MAX, true, true, true);
|
||||
_NUMERIC_LIMITS (unsigned long long, 0, ULLONG_MAX, false, true, true);
|
||||
#endif
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
/// Macro for defining numeric_limits specializations
|
||||
#define NUMERIC_LIMITS(type, minVal, maxVal, bSigned, bInteger, bIntegral) \
|
||||
namespace ustl { _NUMERIC_LIMITS (type, minVal, maxVal, bSigned, bInteger, bIntegral); }
|
||||
|
||||
/// Returns the recommended stream alignment for type \p T. Override with ALIGNOF.
|
||||
template <typename T>
|
||||
inline size_t alignof (const T&)
|
||||
{
|
||||
if (numeric_limits<T>::is_integral)
|
||||
return (__alignof__(T));
|
||||
return (4);
|
||||
}
|
||||
|
||||
#define ALIGNOF(type,grain) \
|
||||
namespace ustl { \
|
||||
template <> inline size_t alignof (const type&) { return (grain); } }
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// ulist.h
|
||||
//
|
||||
|
||||
#ifndef ULIST_H_54E3B510498982C87A0A1E1932E6729D
|
||||
#define ULIST_H_54E3B510498982C87A0A1E1932E6729D
|
||||
|
||||
#include "uvector.h"
|
||||
#include "uctralgo.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// \class list ulist.h ustl.h
|
||||
/// \ingroup Sequences
|
||||
///
|
||||
/// \brief Linked list, defined as an alias to \ref vector.
|
||||
///
|
||||
template <typename T>
|
||||
class list : public vector<T> {
|
||||
public:
|
||||
typedef typename vector<T>::size_type size_type;
|
||||
typedef typename vector<T>::iterator iterator;
|
||||
typedef typename vector<T>::const_iterator const_iterator;
|
||||
typedef typename vector<T>::reference reference;
|
||||
typedef typename vector<T>::const_reference const_reference;
|
||||
public:
|
||||
inline list (void) : vector<T> () {}
|
||||
inline explicit list (size_type n) : vector<T> (n) {}
|
||||
inline list (size_type n, const T& v) : vector<T> (n, v) {}
|
||||
inline list (const list<T>& v) : vector<T> (v) {}
|
||||
inline list (const_iterator i1, const_iterator i2) : vector<T> (i1, i2) {}
|
||||
inline size_type size (void) const { return (vector<T>::size()); }
|
||||
inline iterator begin (void) { return (vector<T>::begin()); }
|
||||
inline const_iterator begin (void) const { return (vector<T>::begin()); }
|
||||
inline iterator end (void) { return (vector<T>::end()); }
|
||||
inline const_iterator end (void) const { return (vector<T>::end()); }
|
||||
inline void push_front (const T& v) { insert (begin(), v); }
|
||||
inline void pop_front (void) { erase (begin()); }
|
||||
inline const_reference front (void) const { return (*begin()); }
|
||||
inline reference front (void) { return (*begin()); }
|
||||
inline void remove (const T& v) { ::ustl::remove (*this, v); }
|
||||
inline void unique (void) { ::ustl::unique (*this); }
|
||||
inline void sort (void) { ::ustl::sort (*this); }
|
||||
void merge (list<T>& l);
|
||||
void splice (iterator ip, list<T>& l, iterator first = NULL, iterator last = NULL);
|
||||
};
|
||||
|
||||
/// Merges the contents with \p l. Assumes both lists are sorted.
|
||||
template <typename T>
|
||||
void list<T>::merge (list& l)
|
||||
{
|
||||
list<T>::resize (size() + l.size());
|
||||
iterator me = merge (begin(), end(), l.begin(), l.end(), begin());
|
||||
list<T>::resize (distance (begin(), me));
|
||||
}
|
||||
|
||||
/// Moves the range [first, last) from \p l to this list at \p ip.
|
||||
template <typename T>
|
||||
void list<T>::splice (iterator ip, list<T>& l, iterator first, iterator last)
|
||||
{
|
||||
if (!first)
|
||||
first = l.begin();
|
||||
if (!last)
|
||||
last = l.end();
|
||||
insert (ip, first, last);
|
||||
l.erase (first, last);
|
||||
}
|
||||
|
||||
#define deque list ///< list has all the functionality provided by deque
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// umap.h
|
||||
//
|
||||
|
||||
#ifndef UMAP_H_45643F516E02A87A3DCEA5024052A6F5
|
||||
#define UMAP_H_45643F516E02A87A3DCEA5024052A6F5
|
||||
|
||||
#include "uassert.h"
|
||||
#include "ufunction.h"
|
||||
#include "uvector.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// \class map umap.h ustl.h
|
||||
/// \ingroup AssociativeContainers
|
||||
///
|
||||
/// \brief A sorted associative container of pair<K,V>
|
||||
///
|
||||
template <typename K, typename V>
|
||||
class map : public vector<pair<K,V> > {
|
||||
public:
|
||||
typedef K key_type;
|
||||
typedef V data_type;
|
||||
typedef const K& const_key_ref;
|
||||
typedef const V& const_data_ref;
|
||||
typedef const map<K,V>& rcself_t;
|
||||
typedef vector<pair<K,V> > base_class;
|
||||
typedef typename base_class::value_type value_type;
|
||||
typedef typename base_class::size_type size_type;
|
||||
typedef typename base_class::pointer pointer;
|
||||
typedef typename base_class::const_pointer const_pointer;
|
||||
typedef typename base_class::reference reference;
|
||||
typedef typename base_class::const_reference const_reference;
|
||||
typedef typename base_class::const_iterator const_iterator;
|
||||
typedef typename base_class::iterator iterator;
|
||||
typedef typename base_class::reverse_iterator reverse_iterator;
|
||||
typedef typename base_class::const_reverse_iterator const_reverse_iterator;
|
||||
typedef pair<const_iterator,const_iterator> const_range_t;
|
||||
typedef pair<iterator,iterator> range_t;
|
||||
public:
|
||||
inline map (void) : vector<pair<K,V> > () {}
|
||||
explicit inline map (size_type n) : vector<pair<K,V> > (n) {}
|
||||
inline map (rcself_t v) : vector<pair<K,V> > (v) {}
|
||||
inline map (const_iterator i1, const_iterator i2) : vector<pair<K,V> >() { insert (i1, i2); }
|
||||
inline rcself_t operator= (rcself_t v) { base_class::operator= (v); return (*this); }
|
||||
inline const_data_ref operator[] (const_key_ref i) const;
|
||||
data_type& operator[] (const_key_ref i);
|
||||
inline size_type size (void) const { return (base_class::size()); }
|
||||
inline iterator begin (void) { return (base_class::begin()); }
|
||||
inline const_iterator begin (void) const { return (base_class::begin()); }
|
||||
inline iterator end (void) { return (base_class::end()); }
|
||||
inline const_iterator end (void) const { return (base_class::end()); }
|
||||
inline void assign (const_iterator i1, const_iterator i2) { clear(); insert (i1, i2); }
|
||||
inline void push_back (const_reference v) { insert (v); }
|
||||
inline const_iterator find (const_key_ref k) const;
|
||||
inline iterator find (const_key_ref k) { return (const_cast<iterator> (const_cast<rcself_t>(*this).find (k))); }
|
||||
inline const_iterator find_data (const_data_ref v, const_iterator first = NULL, const_iterator last = NULL) const;
|
||||
inline iterator find_data (const_data_ref v, iterator first = NULL, iterator last = NULL);
|
||||
iterator insert (const_reference v);
|
||||
void insert (const_iterator i1, const_iterator i2);
|
||||
inline void erase (const_key_ref k);
|
||||
inline iterator erase (iterator ep) { return (base_class::erase (ep)); }
|
||||
inline iterator erase (iterator ep1, iterator ep2) { return (base_class::erase (ep1, ep2)); }
|
||||
inline void clear (void) { base_class::clear(); }
|
||||
private:
|
||||
const_iterator lower_bound (const_key_ref k) const;
|
||||
inline iterator lower_bound (const_key_ref k) { return (const_cast<iterator>(const_cast<rcself_t>(*this).lower_bound (k))); }
|
||||
};
|
||||
|
||||
template <typename K, typename V>
|
||||
typename map<K,V>::const_iterator map<K,V>::lower_bound (const_key_ref k) const
|
||||
{
|
||||
const_iterator first (begin()), last (end());
|
||||
while (first != last) {
|
||||
const_iterator mid = advance (first, distance (first,last) / 2);
|
||||
if (mid->first < k)
|
||||
first = advance (mid, 1);
|
||||
else
|
||||
last = mid;
|
||||
}
|
||||
return (first);
|
||||
}
|
||||
|
||||
/// Returns the pair<K,V> where K = \p k.
|
||||
template <typename K, typename V>
|
||||
inline typename map<K,V>::const_iterator map<K,V>::find (const_key_ref k) const
|
||||
{
|
||||
const_iterator i = lower_bound (k);
|
||||
return ((i < end() && k < i->first) ? end() : i);
|
||||
}
|
||||
|
||||
/// Returns the pair<K,V> where V = \p v, occuring in range [first,last).
|
||||
template <typename K, typename V>
|
||||
inline typename map<K,V>::const_iterator map<K,V>::find_data (const_data_ref v, const_iterator first, const_iterator last) const
|
||||
{
|
||||
if (!first) first = begin();
|
||||
if (!last) last = end();
|
||||
for (; first != last && first->second != v; ++first);
|
||||
return (first);
|
||||
}
|
||||
|
||||
/// Returns the pair<K,V> where V = \p v, occuring in range [first,last).
|
||||
template <typename K, typename V>
|
||||
inline typename map<K,V>::iterator map<K,V>::find_data (const_data_ref v, iterator first, iterator last)
|
||||
{
|
||||
return (const_cast<iterator> (find_data (v, const_cast<const_iterator>(first), const_cast<const_iterator>(last))));
|
||||
}
|
||||
|
||||
/// Returns data associated with key \p k.
|
||||
template <typename K, typename V>
|
||||
inline const typename map<K,V>::data_type& map<K,V>::operator[] (const_key_ref k) const
|
||||
{
|
||||
assert (find(k) != end() && "operator[] const can not insert non-existent keys");
|
||||
return (find(k)->second);
|
||||
}
|
||||
|
||||
/// Returns data associated with key \p k.
|
||||
template <typename K, typename V>
|
||||
typename map<K,V>::data_type& map<K,V>::operator[] (const_key_ref k)
|
||||
{
|
||||
iterator ip = lower_bound (k);
|
||||
if (ip == end() || k < ip->first)
|
||||
ip = base_class::insert (ip, make_pair (k, V()));
|
||||
return (ip->second);
|
||||
}
|
||||
|
||||
/// Inserts the pair into the container.
|
||||
template <typename K, typename V>
|
||||
typename map<K,V>::iterator map<K,V>::insert (const_reference v)
|
||||
{
|
||||
iterator ip = lower_bound (v.first);
|
||||
if (ip == end() || v.first < ip->first)
|
||||
ip = base_class::insert (ip, v);
|
||||
else
|
||||
*ip = v;
|
||||
return (ip);
|
||||
}
|
||||
|
||||
/// Inserts elements from range [i1,i2) into the container.
|
||||
template <typename K, typename V>
|
||||
void map<K,V>::insert (const_iterator i1, const_iterator i2)
|
||||
{
|
||||
assert (i1 <= i2);
|
||||
reserve (size() + distance (i1, i2));
|
||||
for (; i1 != i2; ++i1)
|
||||
insert (*i1);
|
||||
}
|
||||
|
||||
/// Erases the element with key value \p k.
|
||||
template <typename K, typename V>
|
||||
inline void map<K,V>::erase (const_key_ref k)
|
||||
{
|
||||
iterator ip = find (k);
|
||||
if (ip != end())
|
||||
erase (ip);
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// umatrix.h
|
||||
//
|
||||
|
||||
#ifndef UMATRIX_H_740EBFEF554E833645E0FD72419A8185
|
||||
#define UMATRIX_H_740EBFEF554E833645E0FD72419A8185
|
||||
|
||||
#include "utuple.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// \class matrix umatrix.h ustl.h
|
||||
/// \ingroup Sequences
|
||||
///
|
||||
/// \brief A two-dimensional array of NX*NY elements of type T.
|
||||
///
|
||||
template <size_t NX, size_t NY, typename T>
|
||||
class matrix : public tuple<NX*NY,T> {
|
||||
public:
|
||||
typedef tuple<NX,T> row_type;
|
||||
typedef tuple<NY,T> column_type;
|
||||
typedef tuple<NX*NY,T> tuple_type;
|
||||
typedef typename tuple_type::value_type value_type;
|
||||
typedef typename tuple_type::size_type size_type;
|
||||
typedef typename tuple_type::pointer pointer;
|
||||
typedef typename tuple_type::const_pointer const_pointer;
|
||||
typedef typename tuple_type::reference reference;
|
||||
typedef typename tuple_type::const_reference const_reference;
|
||||
typedef typename tuple_type::iterator iterator;
|
||||
typedef typename tuple_type::const_iterator const_iterator;
|
||||
typedef typename tuple_type::range_t range_t;
|
||||
typedef typename tuple_type::const_range_t const_range_t;
|
||||
typedef typename tuple_type::reverse_iterator reverse_iterator;
|
||||
typedef typename tuple_type::const_reverse_iterator const_reverse_iterator;
|
||||
public:
|
||||
inline matrix (void) { fill_n (matrix::begin(), NX*NY, T()); }
|
||||
inline size_type columns (void) const { return (NX); }
|
||||
inline size_type rows (void) const { return (NY); }
|
||||
inline const_iterator at (size_type i) const { return (matrix::begin() + i * NX); }
|
||||
inline iterator at (size_type i) { return (matrix::begin() + i * NX); }
|
||||
inline const_iterator operator[] (size_type i) const { return (at (i)); }
|
||||
inline iterator operator[] (size_type i) { return (at (i)); }
|
||||
inline row_type row (size_type r) const { return (row_type (at (r))); }
|
||||
inline column_type column (size_type c) const;
|
||||
template <typename T2>
|
||||
inline const matrix& operator= (const matrix<NX,NY,T2>& src) { tuple_type::operator= (src); return (*this); }
|
||||
inline const matrix& operator= (const matrix<NX,NY,T>& src) { tuple_type::operator= (src); return (*this); }
|
||||
inline const matrix& operator+= (const_reference v) { tuple_type::operator+= (v); return (*this); }
|
||||
inline const matrix& operator-= (const_reference v) { tuple_type::operator-= (v); return (*this); }
|
||||
inline const matrix& operator*= (const_reference v) { tuple_type::operator*= (v); return (*this); }
|
||||
inline const matrix& operator/= (const_reference v) { tuple_type::operator/= (v); return (*this); }
|
||||
inline const matrix operator+ (const_reference v) const
|
||||
{ matrix result (*this); result += v; return (result); }
|
||||
inline const matrix operator- (const_reference v) const
|
||||
{ matrix result (*this); result -= v; return (result); }
|
||||
inline const matrix operator* (const_reference v) const
|
||||
{ matrix result (*this); result *= v; return (result); }
|
||||
inline const matrix operator/ (const_reference v) const
|
||||
{ matrix result (*this); result /= v; return (result); }
|
||||
};
|
||||
|
||||
template <size_t NX, size_t NY, typename T>
|
||||
inline typename matrix<NX,NY,T>::column_type matrix<NX,NY,T>::column (size_type c) const
|
||||
{
|
||||
column_type result;
|
||||
const_iterator src (matrix::begin() + c);
|
||||
iterator dest (result.begin());
|
||||
for (uoff_t i = 0; i < NY; ++ i, ++ dest, src += NX)
|
||||
*dest = *src;
|
||||
return (result);
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,199 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// umemory.h
|
||||
//
|
||||
|
||||
#ifndef UMEMORY_H_4AB5B0DB5BF09140541409CC47BCD17A
|
||||
#define UMEMORY_H_4AB5B0DB5BF09140541409CC47BCD17A
|
||||
|
||||
#include "unew.h"
|
||||
#ifdef HAVE_ALLOCA_H
|
||||
#include <alloca.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include "upair.h"
|
||||
#include "uiterator.h"
|
||||
#include "ulimits.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// \class auto_ptr umemory.h ustl.h
|
||||
/// \ingroup MemoryManagement
|
||||
///
|
||||
/// \brief A smart pointer.
|
||||
///
|
||||
/// Calls delete in the destructor; assignment transfers ownership.
|
||||
/// This class does not work with void pointers due to the absence
|
||||
/// of the required dereference operator.
|
||||
///
|
||||
template <typename T>
|
||||
class auto_ptr {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef T& reference;
|
||||
public:
|
||||
/// Takes ownership of \p p.
|
||||
inline explicit auto_ptr (pointer p = NULL) : m_p (p) {}
|
||||
/// Takes ownership of pointer in \p p. \p p relinquishes ownership.
|
||||
inline auto_ptr (auto_ptr<T>& p) : m_p (p.release()) {}
|
||||
/// Deletes the owned pointer.
|
||||
inline ~auto_ptr (void) { delete m_p; }
|
||||
/// Returns the pointer without relinquishing ownership.
|
||||
inline pointer get (void) const { return (m_p); }
|
||||
/// Returns the pointer and gives up ownership.
|
||||
inline pointer release (void) { pointer rv (m_p); m_p = NULL; return (rv); }
|
||||
/// Deletes the pointer and sets it equal to \p p.
|
||||
inline void reset (pointer p) { if (p != m_p) { delete m_p; m_p = p; } }
|
||||
/// Takes ownership of \p p.
|
||||
inline auto_ptr<T>& operator= (pointer p) { reset (p); return (*this); }
|
||||
/// Takes ownership of pointer in \p p. \p p relinquishes ownership.
|
||||
inline auto_ptr<T>& operator= (auto_ptr<T>& p) { reset (p.release()); return (*this); }
|
||||
inline reference operator* (void) const { return (*m_p); }
|
||||
inline pointer operator-> (void) const { return (m_p); }
|
||||
inline bool operator== (const pointer p) const { return (m_p == p); }
|
||||
inline bool operator== (const auto_ptr<T>& p) const { return (m_p == p.m_p); }
|
||||
inline bool operator< (const auto_ptr<T>& p) const { return (p.m_p < m_p); }
|
||||
private:
|
||||
pointer m_p;
|
||||
};
|
||||
|
||||
/// Calls the placement new on \p p.
|
||||
/// \ingroup RawStorageAlgorithms
|
||||
///
|
||||
template <typename T>
|
||||
inline void construct (T* p)
|
||||
{
|
||||
new (p) T;
|
||||
}
|
||||
|
||||
/// Calls the placement new on \p p.
|
||||
/// \ingroup RawStorageAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator>
|
||||
inline void construct (ForwardIterator first, ForwardIterator last)
|
||||
{
|
||||
typedef typename iterator_traits<ForwardIterator>::value_type value_type;
|
||||
if (!numeric_limits<value_type>::is_integral) {
|
||||
while (first < last) {
|
||||
construct (&*first);
|
||||
++ first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls the placement new on \p p.
|
||||
/// \ingroup RawStorageAlgorithms
|
||||
///
|
||||
template <typename T>
|
||||
inline void construct (T* p, const T& value)
|
||||
{
|
||||
new (p) T (value);
|
||||
}
|
||||
|
||||
/// Calls the destructor of \p p without calling delete.
|
||||
/// \ingroup RawStorageAlgorithms
|
||||
///
|
||||
template <typename T>
|
||||
inline void destroy (T* p) throw()
|
||||
{
|
||||
p->~T();
|
||||
}
|
||||
|
||||
/// Calls the destructor on elements in range [first, last) without calling delete.
|
||||
/// \ingroup RawStorageAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator>
|
||||
inline void destroy (ForwardIterator first, ForwardIterator last) throw()
|
||||
{
|
||||
typedef typename iterator_traits<ForwardIterator>::value_type value_type;
|
||||
if (!numeric_limits<value_type>::is_integral)
|
||||
for (; first < last; ++ first)
|
||||
destroy (&*first);
|
||||
}
|
||||
|
||||
/// Casts \p p to the type of the second pointer argument.
|
||||
template <typename T> inline T* cast_to_type (void* p, const T*) { return ((T*) p); }
|
||||
|
||||
/// \brief Creates a temporary buffer pair from \p p and \p n
|
||||
/// This is intended to be used with alloca to create temporary buffers.
|
||||
/// The size in the returned pair is set to 0 if the allocation is unsuccessful.
|
||||
/// \ingroup RawStorageAlgorithms
|
||||
///
|
||||
template <typename T>
|
||||
inline pair<T*, ptrdiff_t> make_temporary_buffer (void* p, size_t n, const T* ptype)
|
||||
{
|
||||
return (make_pair (cast_to_type(p,ptype), ptrdiff_t(p ? n : 0)));
|
||||
}
|
||||
|
||||
#ifdef HAVE_ALLOCA_H
|
||||
/// \brief Allocates a temporary buffer, if possible.
|
||||
/// \ingroup RawStorageAlgorithms
|
||||
#define get_temporary_buffer(size, ptype) make_temporary_buffer (alloca(size_of_elements(size, ptype)), size, ptype)
|
||||
#define return_temporary_buffer(p)
|
||||
#else
|
||||
#define get_temporary_buffer(size, ptype) make_temporary_buffer (malloc(size_of_elements(size, ptype)), size, ptype)
|
||||
#define return_temporary_buffer(p) if (p) free (p), p = NULL
|
||||
#endif
|
||||
|
||||
/// Copies [first, last) into result by calling copy constructors in result.
|
||||
/// \ingroup RawStorageAlgorithms
|
||||
///
|
||||
template <typename InputIterator, typename ForwardIterator>
|
||||
ForwardIterator uninitialized_copy (InputIterator first, InputIterator last, ForwardIterator result)
|
||||
{
|
||||
while (first < last) {
|
||||
construct (&*result, *first);
|
||||
++ result;
|
||||
++ first;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/// Copies [first, first + n) into result by calling copy constructors in result.
|
||||
/// \ingroup RawStorageAlgorithms
|
||||
///
|
||||
template <typename InputIterator, typename ForwardIterator>
|
||||
ForwardIterator uninitialized_copy_n (InputIterator first, size_t n, ForwardIterator result)
|
||||
{
|
||||
while (n--) {
|
||||
construct (&*result, *first);
|
||||
++ result;
|
||||
++ first;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/// Calls construct on all elements in [first, last) with value \p v.
|
||||
/// \ingroup RawStorageAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator, typename T>
|
||||
void uninitialized_fill (ForwardIterator first, ForwardIterator last, const T& v)
|
||||
{
|
||||
while (first < last) {
|
||||
construct (&*first, v);
|
||||
++ first;
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls construct on all elements in [first, first + n) with value \p v.
|
||||
/// \ingroup RawStorageAlgorithms
|
||||
///
|
||||
template <typename ForwardIterator, typename T>
|
||||
ForwardIterator uninitialized_fill_n (ForwardIterator first, size_t n, const T& v)
|
||||
{
|
||||
while (n--) {
|
||||
construct (&*first, v);
|
||||
++ first;
|
||||
}
|
||||
return (first);
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// umultimap.h
|
||||
//
|
||||
|
||||
#ifndef UMULTIMAP_H_45743F516E02A87A3FCEA5024052A6F5
|
||||
#define UMULTIMAP_H_45743F516E02A87A3FCEA5024052A6F5
|
||||
|
||||
#include "uassert.h"
|
||||
#include "ufunction.h"
|
||||
#include "uvector.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// \class multimap umultimap.h ustl.h
|
||||
/// \ingroup AssociativeContainers
|
||||
///
|
||||
/// \brief A sorted associative container that may container multiple entries for each key.
|
||||
///
|
||||
template <typename K, typename V>
|
||||
class multimap : public vector<pair<K,V> > {
|
||||
public:
|
||||
typedef K key_type;
|
||||
typedef V data_type;
|
||||
typedef const K& const_key_ref;
|
||||
typedef const V& const_data_ref;
|
||||
typedef const multimap<K,V>& rcself_t;
|
||||
typedef vector<pair<K,V> > base_class;
|
||||
typedef typename base_class::value_type value_type;
|
||||
typedef typename base_class::size_type size_type;
|
||||
typedef typename base_class::pointer pointer;
|
||||
typedef typename base_class::const_pointer const_pointer;
|
||||
typedef typename base_class::reference reference;
|
||||
typedef typename base_class::const_reference const_reference;
|
||||
typedef typename base_class::const_iterator const_iterator;
|
||||
typedef typename base_class::iterator iterator;
|
||||
typedef typename base_class::reverse_iterator reverse_iterator;
|
||||
typedef typename base_class::const_reverse_iterator const_reverse_iterator;
|
||||
typedef pair<const_iterator,const_iterator> const_range_t;
|
||||
typedef pair<iterator,iterator> range_t;
|
||||
public:
|
||||
inline multimap (void) : vector<pair<K,V> > () {}
|
||||
explicit inline multimap (size_type n) : vector<pair<K,V> > (n) {}
|
||||
inline multimap (rcself_t v) : vector<pair<K,V> > (v) {}
|
||||
inline multimap (const_iterator i1, const_iterator i2) : vector<pair<K,V> > () { insert (i1, i2); }
|
||||
inline rcself_t operator= (rcself_t v) { base_class::operator= (v); return (*this); }
|
||||
inline size_type size (void) const { return (base_class::size()); }
|
||||
inline iterator begin (void) { return (base_class::begin()); }
|
||||
inline const_iterator begin (void) const { return (base_class::begin()); }
|
||||
inline iterator end (void) { return (base_class::end()); }
|
||||
inline const_iterator end (void) const { return (base_class::end()); }
|
||||
inline void assign (const_iterator i1, const_iterator i2) { clear(); insert (i1, i2); }
|
||||
inline size_type count (const_key_ref k) const { return (upper_bound(k) - lower_bound(k)); }
|
||||
inline void push_back (const_reference v) { insert (v); }
|
||||
inline const_range_t equal_range (const_key_ref k) const { return (make_pair (lower_bound(k), upper_bound(k))); }
|
||||
inline range_t equal_range (const_key_ref k) { return (make_pair (const_cast<iterator>(lower_bound(k)), const_cast<iterator>(upper_bound(k)))); }
|
||||
const_iterator lower_bound (const_key_ref k) const;
|
||||
const_iterator upper_bound (const_key_ref k) const;
|
||||
inline iterator insert (const_reference v);
|
||||
void insert (const_iterator i1, const_iterator i2);
|
||||
inline void erase (const_key_ref k) { erase (const_cast<iterator>(lower_bound(k)), const_cast<iterator>(upper_bound(k))); }
|
||||
inline iterator erase (iterator ep) { return (base_class::erase (ep)); }
|
||||
inline iterator erase (iterator ep1, iterator ep2) { return (base_class::erase (ep1, ep2)); }
|
||||
inline void clear (void) { base_class::clear(); }
|
||||
};
|
||||
|
||||
/// Returns an iterator to the first element with key value \p k.
|
||||
template <typename K, typename V>
|
||||
typename multimap<K,V>::const_iterator multimap<K,V>::lower_bound (const_key_ref k) const
|
||||
{
|
||||
const_iterator first (begin()), last (end());
|
||||
while (first != last) {
|
||||
const_iterator mid = advance (first, distance (first,last) / 2);
|
||||
if (mid->first < k)
|
||||
first = advance (mid, 1);
|
||||
else
|
||||
last = mid;
|
||||
}
|
||||
return (first);
|
||||
}
|
||||
|
||||
/// Returns an iterator to the first element with key value \p k.
|
||||
template <typename K, typename V>
|
||||
typename multimap<K,V>::const_iterator multimap<K,V>::upper_bound (const_key_ref k) const
|
||||
{
|
||||
const_iterator first (begin()), last (end());
|
||||
while (first != last) {
|
||||
const_iterator mid = advance (first, distance (first,last) / 2);
|
||||
if (k < mid->first)
|
||||
last = mid;
|
||||
else
|
||||
first = advance (mid, 1);
|
||||
}
|
||||
return (last);
|
||||
}
|
||||
|
||||
/// Inserts the pair into the container.
|
||||
template <typename K, typename V>
|
||||
inline typename multimap<K,V>::iterator multimap<K,V>::insert (const_reference v)
|
||||
{
|
||||
iterator ip = const_cast<iterator> (upper_bound (v.first));
|
||||
return (base_class::insert (ip, v));
|
||||
}
|
||||
|
||||
/// Inserts elements from range [i1,i2) into the container.
|
||||
template <typename K, typename V>
|
||||
void multimap<K,V>::insert (const_iterator i1, const_iterator i2)
|
||||
{
|
||||
assert (i1 <= i2);
|
||||
reserve (size() + distance (i1, i2));
|
||||
for (; i1 != i2; ++i1)
|
||||
insert (*i1);
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
// This file is part of the ustl library, an STL implementation.
|
||||
//
|
||||
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
|
||||
// This file is free software, distributed under the MIT License.
|
||||
//
|
||||
// umultiset.h
|
||||
//
|
||||
|
||||
#ifndef UMULTISET_H_446AEDBB7F61C6994DC228C25D5FA3A1
|
||||
#define UMULTISET_H_446AEDBB7F61C6994DC228C25D5FA3A1
|
||||
|
||||
#include "uassert.h"
|
||||
#include "ualgo.h"
|
||||
#include "uvector.h"
|
||||
|
||||
namespace ustl {
|
||||
|
||||
/// \class multiset umultiset.h ustl.h
|
||||
/// \ingroup AssociativeContainers
|
||||
///
|
||||
/// \brief Multiple sorted container.
|
||||
/// Unlike set, it may contain multiple copies of each element.
|
||||
///
|
||||
template <typename T>
|
||||
class multiset : public vector<T> {
|
||||
public:
|
||||
typedef const multiset<T>& rcself_t;
|
||||
typedef vector<T> base_class;
|
||||
typedef typename base_class::value_type value_type;
|
||||
typedef typename base_class::size_type size_type;
|
||||
typedef typename base_class::pointer pointer;
|
||||
typedef typename base_class::const_pointer const_pointer;
|
||||
typedef typename base_class::reference reference;
|
||||
typedef typename base_class::const_reference const_reference;
|
||||
typedef typename base_class::const_iterator const_iterator;
|
||||
typedef typename base_class::iterator iterator;
|
||||
typedef typename base_class::reverse_iterator reverse_iterator;
|
||||
typedef typename base_class::const_reverse_iterator const_reverse_iterator;
|
||||
public:
|
||||
inline multiset (void) : vector<T> () {}
|
||||
explicit inline multiset (size_type n) : vector<T> (n) {}
|
||||
inline multiset (rcself_t v) : vector<T> (v) {}
|
||||
inline multiset (const_iterator i1, const_iterator i2) : vector<T> () { insert (i1, i2); }
|
||||
inline rcself_t operator= (rcself_t v) { base_class::operator= (v); return (*this); }
|
||||
inline size_type size (void) const { return (base_class::size()); }
|
||||
inline iterator begin (void) { return (base_class::begin()); }
|
||||
inline const_iterator begin (void) const { return (base_class::begin()); }
|
||||
inline iterator end (void) { return (base_class::end()); }
|
||||
inline const_iterator end (void) const { return (base_class::end()); }
|
||||
inline void assign (const_iterator i1, const_iterator i2);
|
||||
size_type count (const_reference v) const;
|
||||
inline void push_back (const_reference v) { insert (v); }
|
||||
inline iterator insert (const_reference v);
|
||||
void insert (const_iterator i1, const_iterator i2);
|
||||
void erase (const_reference v);
|
||||
inline iterator erase (iterator ep) { return (base_class::erase (ep)); }
|
||||
inline iterator erase (iterator ep1, iterator ep2) { return (base_class::erase (ep1, ep2)); }
|
||||
inline void clear (void) { base_class::clear(); }
|
||||
};
|
||||
|
||||
/// Copies contents of range [i1,i2)
|
||||
template <typename T>
|
||||
inline void multiset<T>::assign (const_iterator i1, const_iterator i2)
|
||||
{
|
||||
base_class::clear();
|
||||
insert (i1, i2);
|
||||
}
|
||||
|
||||
/// Returns the number of elements of value \p v.
|
||||
template <typename T>
|
||||
typename multiset<T>::size_type multiset<T>::count (const_reference v) const
|
||||
{
|
||||
const pair<const_iterator,const_iterator> fr = equal_range (begin(), end(), v);
|
||||
return (distance (fr.first, fr.second));
|
||||
}
|
||||
|
||||
/// Inserts \p v.
|
||||
template <typename T>
|
||||
inline typename multiset<T>::iterator multiset<T>::insert (const_reference v)
|
||||
{
|
||||
iterator ip = upper_bound (begin(), end(), v);
|
||||
return (base_class::insert (ip, v));
|
||||
}
|
||||
|
||||
/// Inserts all elements from range [i1,i2).
|
||||
template <typename T>
|
||||
void multiset<T>::insert (const_iterator i1, const_iterator i2)
|
||||
{
|
||||
assert (i1 <= i2);
|
||||
reserve (size() + distance (i1, i2));
|
||||
for (; i1 < i2; ++i1)
|
||||
push_back (*i1);
|
||||
}
|
||||
|
||||
/// Erases all elements with value \p v.
|
||||
template <typename T>
|
||||
void multiset<T>::erase (const_reference v)
|
||||
{
|
||||
pair<iterator,iterator> epr = equal_range (begin(), end(), v);
|
||||
erase (epr.first, epr.second);
|
||||
}
|
||||
|
||||
} // namespace ustl
|
||||
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user