153 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*  $Id$
 | 
						|
 | 
						|
    Part of SWI-Prolog
 | 
						|
 | 
						|
    Author:        Jan Wielemaker
 | 
						|
    E-mail:        wielemak@science.uva.nl
 | 
						|
    WWW:           http://www.swi-prolog.org
 | 
						|
    Copyright (C): 1985-2007, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
						|
*/
 | 
						|
 | 
						|
#include <SWI-Stream.h>
 | 
						|
#include <SWI-Prolog.h>
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
#define TRYPUTC(c, s) if ( Sputcode(c, s) < 0 ) { return -1; }
 | 
						|
 | 
						|
static int
 | 
						|
json_put_code(IOSTREAM *out, int c)
 | 
						|
{ static char escape[128];
 | 
						|
  static int escape_initialized = FALSE;
 | 
						|
 | 
						|
  if ( !escape_initialized )
 | 
						|
  { memset(escape, 0, sizeof(escape));
 | 
						|
 | 
						|
    escape['"']  = '"';
 | 
						|
    escape['\\'] = '\\';
 | 
						|
    escape['\b'] = 'b';
 | 
						|
    escape['\f'] = 'f';
 | 
						|
    escape['\n'] = 'n';
 | 
						|
    escape['\r'] = 'r';
 | 
						|
    escape['\t'] = 't';
 | 
						|
 | 
						|
    escape_initialized = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( c < 128 )
 | 
						|
  { if ( escape[c] )
 | 
						|
    { TRYPUTC('\\', out);
 | 
						|
      TRYPUTC(escape[c], out);
 | 
						|
    } else if ( c < ' ' )	/* control characters *must* be escaped */
 | 
						|
    { TRYPUTC('\\', out);
 | 
						|
      if ( Sfprintf(out, "u%04x", c) < 0 )
 | 
						|
	return -1;
 | 
						|
    } else
 | 
						|
    { TRYPUTC(c, out);
 | 
						|
    }
 | 
						|
  } else
 | 
						|
  { TRYPUTC(c, out);
 | 
						|
  }
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
#undef TRYPUTC
 | 
						|
#define TRYPUTC(c, s) if ( Sputcode(c, s) < 0 ) { rc = FALSE; goto out; }
 | 
						|
 | 
						|
static foreign_t
 | 
						|
json_write_string(term_t stream, term_t text)
 | 
						|
{ IOSTREAM *out;
 | 
						|
  char *a;
 | 
						|
  pl_wchar_t *w;
 | 
						|
  size_t len;
 | 
						|
  int rc = TRUE;
 | 
						|
 | 
						|
  if ( !PL_get_stream_handle(stream, &out) )
 | 
						|
    return FALSE;
 | 
						|
 | 
						|
  if ( PL_get_nchars(text, &len, &a, CVT_ATOM|CVT_STRING|CVT_LIST) )
 | 
						|
  { const char *ap;
 | 
						|
    size_t todo;
 | 
						|
 | 
						|
    TRYPUTC('"', out);
 | 
						|
    for(todo=len, ap=a; todo-- > 0; ap++)
 | 
						|
    { int c = *ap&0xff;
 | 
						|
 | 
						|
      if ( json_put_code(out, c) < 0 )
 | 
						|
      { rc = FALSE; goto out;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    TRYPUTC('"', out);
 | 
						|
  } else if ( PL_get_wchars(text, &len, &w, CVT_ATOM|CVT_STRING|CVT_LIST|CVT_EXCEPTION) )
 | 
						|
  { const pl_wchar_t *wp;
 | 
						|
    size_t todo;
 | 
						|
 | 
						|
    TRYPUTC('"', out);
 | 
						|
    for(todo=len, wp=w; todo-- > 0; wp++)
 | 
						|
    { int c = *wp;
 | 
						|
 | 
						|
      if ( json_put_code(out, c) < 0 )
 | 
						|
      { rc = FALSE; goto out;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    TRYPUTC('"', out);
 | 
						|
  } else
 | 
						|
  { rc = FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
out:
 | 
						|
  PL_release_stream(out);
 | 
						|
 | 
						|
  return rc;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static foreign_t
 | 
						|
json_write_indent(term_t stream, term_t indent, term_t tab)
 | 
						|
{ int i, t, n;
 | 
						|
  IOSTREAM *out;
 | 
						|
 | 
						|
  if ( !PL_get_integer(indent, &i) ||
 | 
						|
       !PL_get_integer(tab, &t) )
 | 
						|
    return FALSE;
 | 
						|
 | 
						|
  if ( PL_get_stream_handle(stream, &out) )
 | 
						|
  { int rc = TRUE;
 | 
						|
 | 
						|
    if ( !out->position || out->position->linepos > 0 )
 | 
						|
    { TRYPUTC('\n', out);
 | 
						|
    }
 | 
						|
    for(n=0; n<i/t; n++)
 | 
						|
      TRYPUTC('\t', out);
 | 
						|
    for(n=0; n<i%t; n++)
 | 
						|
      TRYPUTC(' ', out);
 | 
						|
out:
 | 
						|
    PL_release_stream(out);
 | 
						|
    return rc;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
install_t
 | 
						|
install_json()
 | 
						|
{ PL_register_foreign("json_write_string", 2, json_write_string, 0);
 | 
						|
  PL_register_foreign("json_write_indent", 3, json_write_indent, 0);
 | 
						|
}
 |