/* $Id$ Part of SWI-Prolog Author: Jan Wielemaker E-mail: J.Wielemaker@uva.nl WWW: http://www.swi-prolog.org Copyright (C): 1985-2011, University of Amsterdam This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "pl-incl.h" #if __YAP_PROLOG__ #include "pl-codelist.h" #else #include "../pl-codelist.h" #endif /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - codes_or_chars_to_buffer(term_t l, unsigned int flags, int wide, CVT_code *status) If l represents a list of codes or characters, return a buffer holding the characters. If wide == TRUE the buffer contains objects of type pl_wchar_t. Otherwise it contains traditional characters. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ Buffer codes_or_chars_to_buffer(term_t l, unsigned int flags, int wide, CVT_result *result) { GET_LD Buffer b; word list = valHandle(l); word slow; Word arg, tail; int step_slow = TRUE; enum { CHARS, CODES } type; if ( isList(list) ) { intptr_t c = -1; arg = argTermP(list, 0); deRef(arg); if ( isTaggedInt(*arg) ) { c = valInt(*arg); type = CODES; } else { c = charCode(*arg); type = CHARS; } result->culprit = *arg; if ( c < 0 || (!wide && c > 0xff) ) { if ( canBind(*arg) ) result->status = CVT_partial; else if ( c < 0 ) result->status = CVT_nocode; else if ( c > 0xff ) result->status = CVT_wide; return NULL; } } else if ( isNil(list) ) { return findBuffer(flags); } else { if ( canBind(list) ) result->status = CVT_partial; else result->status = CVT_nolist; return NULL; } b = findBuffer(flags); slow = list; while( isList(list) ) { intptr_t c = -1; arg = argTermP(list, 0); deRef(arg); switch(type) { case CODES: if ( isTaggedInt(*arg) ) c = valInt(*arg); break; case CHARS: c = charCode(*arg); break; } if ( c < 0 || (!wide && c > 0xff) ) { result->culprit = *arg; unfindBuffer(flags); /* TBD: check unicode range */ if ( canBind(*arg) ) result->status = CVT_partial; else if ( c < 0 ) result->status = (type == CODES ? CVT_nocode : CVT_nochar); else if ( c > 0xff ) result->status = CVT_wide; return NULL; } if ( wide ) addBuffer(b, (pl_wchar_t)c, pl_wchar_t); else addBuffer(b, (unsigned char)c, unsigned char); tail = argTermP(list, 1); deRef(tail); list = *tail; if ( list == slow ) /* cyclic */ { unfindBuffer(flags); result->status = CVT_nolist; return NULL; } if ( (step_slow = !step_slow) ) { tail = argTermP(slow, 1); deRef(tail); slow = *tail; } } if ( !isNil(list) ) { unfindBuffer(flags); if ( canBind(list) ) result->status = CVT_partial; else result->status = CVT_nolist; return NULL; } result->status = CVT_ok; return b; }