Skip to content
Snippets Groups Projects
Transcoder.cpp 4.39 KiB
Newer Older
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdlib.h>
#include "Transcoder.hpp"

XERCES_CPP_NAMESPACE_USE

static bool DEBUG_IN = false;
static bool DEBUG_OUT = false;

Transcoder* Transcoder::_instance = NULL;

Transcoder*
Transcoder::getInstance() {
  // fprintf(stderr, "getInstance: finding instance\n");
  if (_instance == NULL) {
    // fprintf(stderr, "getInstance: making new transcoder\n");
    _instance = new Transcoder();
  }
  return _instance;
}

Transcoder::~Transcoder() {
  // fprintf(stderr, "Deleting transcoder\n");
}

Transcoder::Transcoder() {
  XMLTransService::Codes failReason;

  // we assume that the Xerces-C transcoding service is already initialized
  // via XMLPlatformUtils::Initialize()
  UTF8_TRANSCODER = XMLPlatformUtils::fgTransService->makeNewTranscoderFor(
						XMLUni::fgUTF8EncodingString,
						failReason,
						1024);

  if (UTF8_TRANSCODER == NULL) {
    croak("ERROR: Transcoder Could not create UTF-8 transcoder");
  } else if (failReason == XMLTransService::UnsupportedEncoding) {
    croak("ERROR: Transcoder: unsupported encoding");
  } else if (failReason == XMLTransService::InternalFailure) {
    croak("ERROR: Transcoder: internal failure");
  } else if (failReason == XMLTransService::SupportFilesNotFound) {
    croak("ERROR: Transcoder: support files not found");
  } else if (failReason == XMLTransService::Ok) {
    // fprintf(stderr, "Created transcoder ok\n");
  }
}

SV*
Transcoder::XMLString2Local(const XMLCh* input) {
  if (input == NULL) {
    return &PL_sv_undef;
  }

  XMLSize_t charsEaten = 0;
  int length  = XMLString::stringLen(input);            // string length
  // use +1 to make room for the '\0' at the end of the string
  // in the pathological case when each character of the string 
  // is UTF8_MAXLEN bytes long
  XMLByte* res = new XMLByte[(length * UTF8_MAXLEN) + 1]; // output string

  XMLSize_t total_chars =
    UTF8_TRANSCODER->transcodeTo((const XMLCh*) input, 
				   (XMLSize_t) (length*UTF8_MAXLEN),
				   charsEaten,
				   XMLTranscoder::UnRep_Throw
				   );
  res[total_chars] = '\0';

#if (0) 
  if (DEBUG_OUT) {
      printf("Xerces out length = %d: ",total_chars);
      for (int i=0;i<length;i++){
	  printf("<0x%.4X>",res[i]);
      }
      printf("\n");
  }
#endif

  output = sv_newmortal();
  sv_setpv((SV*)output, (char *)res );
  SvUTF8_on((SV*)output);
  delete[] res;
  return output;
}

XMLCh* 
Transcoder::Local2XMLString(SV* input){

    if (input == &PL_sv_undef) {
      return NULL;
    }

    XMLCh* output;

    STRLEN length;
    char *ptr = (char *)SvPVutf8(input,length);

#if (0) 
    if (DEBUG_IN) {
	printf("Perl in length = %d: ",length);
	for (unsigned int i=0;i<length;i++){
	    printf("<0x%.4X>",ptr[i]);
	}
	printf("\n");
    }
#endif

    if (SvUTF8(input)) {
	XMLSize_t charsEaten = 0;
        unsigned char* sizes = new unsigned char[length+1];
        output = new XMLCh[length+1];
	XMLSize_t chars_stored = 
	    UTF8_TRANSCODER->transcodeFrom((const XMLByte*) ptr,
					   charsEaten,
					   (unsigned char*)sizes
					   );
	delete [] sizes;

#if (0) 
	if (DEBUG_IN) {
	    printf("Xerces in length = %d: ",chars_stored);
	    for (unsigned int i=0;i<chars_stored;i++){
		printf("<0x%.4X>",output[i]);
	    }
	    printf("\n");
	}
#endif

	// indicate the end of the string
	output[chars_stored] = '\0';
    } else {
	output = XMLString::transcode(ptr);

#if (0) 
	if (DEBUG_IN) {
	    printf("Xerces: ");
	    for (int i=0;output[i];i++){
		printf("<0x%.4X>",output[i]);
	    }
	    printf("\n");
	}
#endif

    }
    return(output);
}