content: /*
   * This library is part of OpenCms -
   * the Open Source Content Management System
   *
   * Copyright (c) Alkacon Software GmbH & Co. KG (https://www.alkacon.com)
   *
   * 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.
   *
   * For further information about Alkacon Software GmbH & Co. KG, please see the
   * company website: https://www.alkacon.com
   *
   * For further information about OpenCms, please see the
   * project website: https://www.opencms.org
   *
   * 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
   *
   * This file is based on:
   * org.json.CDL
   * from the JSON in Java implementation.
   *
   * Copyright (c) 2002 JSON.org
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in all
   * copies or substantial portions of the Software.
   *
   * The Software shall be used for Good, not Evil.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   * SOFTWARE.
   */
  
  package org.opencms.json;
  
  /**
   * This provides static methods to convert comma delimited text into a
   * JSONArray, and to covert a JSONArray into comma delimited text. Comma
   * delimited text is a very popular format for data interchange. It is
   * understood by most database, spreadsheet, and organizer programs.
   * <p>
   * Each row of text represents a row in a table or a data record. Each row
   * ends with a NEWLINE character. Each row contains one or more values.
   * Values are separated by commas. A value can contain any character except
   * for comma, unless is is wrapped in single quotes or double quotes.
   * <p>
   * The first row usually contains the names of the columns.
   * <p>
   * A comma delimited list can be converted into a JSONArray of JSONObjects.
   * The names for the elements in the JSONObjects can be taken from the names
   * in the first row.<p>
   *
   */
  public final class CDL {
  
      /**
       * Hidden constructor.<p>
       */
      private CDL() {
  
          // hidden constructor
      }
  
      /**
       * Produce a JSONArray of strings from a row of comma delimited values.<p>
       *
       * @param x A JSONTokener of the source text
       * @return A JSONArray of strings
       * @throws JSONException if something goes wrong
       */
      public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException {
  
          JSONArray ja = new JSONArray();
          for (;;) {
              String value = getValue(x);
              if ((value == null) || ((ja.length() == 0) && (value.length() == 0))) {
                  return null;
              }
              ja.put(value);
              for (;;) {
                  char c = x.next();
                  if (c == ',') {
                      break;
                  }
                  if (c != ' ') {
                      if ((c == '\n') || (c == '\r') || (c == 0)) {
                          return ja;
                      }
                      throw x.syntaxError("Bad character '" + c + "' (" + (int)c + ").");
                  }
              }
          }
      }
  
      /**
       * Produce a JSONObject from a row of comma delimited text, using a
       * parallel JSONArray of strings to provides the names of the elements.<p>
       *
       * @param names A JSONArray of names. This is commonly obtained from the
       *  first row of a comma delimited text file using the rowToJSONArray
       *  method
       * @param x A JSONTokener of the source text
       * @return A JSONObject combining the names and values
       * @throws JSONException if something goes wrong
       */
      public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x) throws JSONException {
  
          JSONArray ja = rowToJSONArray(x);
          return ja != null ? ja.toJSONObject(names) : null;
      }
  
      /**
       * Produce a comma delimited text row from a JSONArray. Values containing
       * the comma character will be quoted.<p>
       *
       * @param ja A JSONArray of strings
       * @return A string ending in NEWLINE
       */
      public static String rowToString(JSONArray ja) {
  
          StringBuffer sb = new StringBuffer();
          for (int i = 0; i < ja.length(); i += 1) {
              if (i > 0) {
                  sb.append(',');
              }
              Object o = ja.opt(i);
              if (o != null) {
                  String s = o.toString();
                  if (s.indexOf(',') >= 0) {
                      if (s.indexOf('"') >= 0) {
                          sb.append('\'');
                          sb.append(s);
                          sb.append('\'');
                      } else {
                          sb.append('"');
                          sb.append(s);
                          sb.append('"');
                      }
                  } else {
                      sb.append(s);
                  }
              }
          }
          sb.append('\n');
          return sb.toString();
  
      }
  
      /**
       * Produce a JSONArray of JSONObjects from a comma delimited text string
       * using a supplied JSONArray as the source of element names.<p>
       *
       * @param names A JSONArray of strings
       * @param x A JSONTokener of the source text
       * @return A JSONArray of JSONObjects
       * @throws JSONException if something goes wrong
       */
      public static JSONArray toJSONArray(JSONArray names, JSONTokener x) throws JSONException {
  
          if ((names == null) || (names.length() == 0)) {
              return null;
          }
          JSONArray ja = new JSONArray();
          for (;;) {
              JSONObject jo = rowToJSONObject(names, x);
              if (jo == null) {
                  break;
              }
              ja.put(jo);
          }
          if (ja.length() == 0) {
              return null;
          }
          return ja;
      }
  
      /**
       * Produce a JSONArray of JSONObjects from a comma delimited text string
       * using a supplied JSONArray as the source of element names.<p>
       *
       * @param names A JSONArray of strings.
       * @param string The comma delimited text
       * @return A JSONArray of JSONObjects
       * @throws JSONException if something goes wrong
       */
      public static JSONArray toJSONArray(JSONArray names, String string) throws JSONException {
  
          return toJSONArray(names, new JSONTokener(string));
      }
  
      /**
       * Produce a JSONArray of JSONObjects from a comma delimited text string,
       * using the first row as a source of names.<p>
       *
       * @param x The JSONTokener containing the comma delimited text
       * @return A JSONArray of JSONObjects
       * @throws JSONException if something goes wrong
       */
      public static JSONArray toJSONArray(JSONTokener x) throws JSONException {
  
          return toJSONArray(rowToJSONArray(x), x);
      }
  
      /**
       * Produce a JSONArray of JSONObjects from a comma delimited text string,
       * using the first row as a source of names.<p>
       *
       * @param string The comma delimited text
       * @return A JSONArray of JSONObjects
       * @throws JSONException if something goes wrong
       */
      public static JSONArray toJSONArray(String string) throws JSONException {
  
          return toJSONArray(new JSONTokener(string));
      }
  
      /**
       * Produce a comma delimited text from a JSONArray of JSONObjects. The
       * first row will be a list of names obtained by inspecting the first
       * JSONObject.<p>
       *
       * @param ja A JSONArray of JSONObjects
       * @return A comma delimited text
       * @throws JSONException if something goes wrong
       */
      public static String toString(JSONArray ja) throws JSONException {
  
          JSONObject jo = ja.optJSONObject(0);
          if (jo != null) {
              JSONArray names = jo.names();
              if (names != null) {
                  return rowToString(names) + toString(names, ja);
              }
          }
          return null;
      }
  
      /**
       * Produce a comma delimited text from a JSONArray of JSONObjects using
       * a provided list of names. The list of names is not included in the
       * output.<p>
       *
       * @param names A JSONArray of strings
       * @param ja A JSONArray of JSONObjects
       * @return A comma delimited text
       * @throws JSONException if something goes wrong
       */
      public static String toString(JSONArray names, JSONArray ja) throws JSONException {
  
          if ((names == null) || (names.length() == 0)) {
              return null;
          }
          StringBuffer sb = new StringBuffer();
          for (int i = 0; i < ja.length(); i += 1) {
              JSONObject jo = ja.optJSONObject(i);
              if (jo != null) {
                  sb.append(rowToString(jo.toJSONArray(names)));
              }
          }
          return sb.toString();
      }
  
      /**
       * Get the next value. The value can be wrapped in quotes. The value can
       * be empty.<p>
       *
       * @param x A JSONTokener of the source text
       * @return The value string, or null if empty
       * @throws JSONException if the quoted string is badly formed
       */
      private static String getValue(JSONTokener x) throws JSONException {
  
          char c;
          do {
              c = x.next();
          } while ((c == ' ') || (c == '\t'));
          switch (c) {
              case 0:
                  return null;
              case '"':
              case '\'':
                  return x.nextString(c);
              case ',':
                  x.back();
                  return "";
              default:
                  x.back();
                  return x.nextTo(',');
          }
      }
  }
  